From 7af6a96a132bfb6b93026f19d0320a8fc644ad18 Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Thu, 29 May 2014 16:30:07 +0100 Subject: [PATCH] mmap: added mmap io to gpio * added function to gpio to use mmap * changed board definition format around mmap io (fast-gpio) * Intel Galileo Rev D updated to follow changed definitions * Example performing mmap io to pin 2 added. Signed-off-by: Thomas Ingleby --- api/gpio.h | 8 +++++ api/maa.h | 19 ++++++++--- examples/CMakeLists.txt | 2 ++ examples/mmap-io2.c | 47 ++++++++++++++++++++++++++ include/maa_internal.h | 7 ++++ src/gpio/gpio.c | 69 +++++++++++++++++++++++++++++++++++++-- src/intel_galileo_rev_d.c | 22 ++++++++++--- src/maa.c | 19 +++++++++++ 8 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 examples/mmap-io2.c diff --git a/api/gpio.h b/api/gpio.h index b371154..0af268c 100644 --- a/api/gpio.h +++ b/api/gpio.h @@ -175,6 +175,14 @@ maa_result_t maa_gpio_write(maa_gpio_context dev, int value); */ maa_result_t maa_gpio_owner(maa_gpio_context dev, maa_boolean_t owner); +/** Enable using memory mapped io instead of sysfs + * + * @param dev gpio context + * @param mmap use mmap instead of sysfs + * @return maa_result type + */ +maa_result_t maa_gpio_use_mmaped(maa_gpio_context dev, maa_boolean_t mmap); + #ifdef __cplusplus } #endif diff --git a/api/maa.h b/api/maa.h index 6fe7956..0c83c3b 100644 --- a/api/maa.h +++ b/api/maa.h @@ -103,13 +103,22 @@ typedef struct { */ typedef struct { /*@{*/ - unsigned int pinmap; - unsigned int parent_id; - unsigned int mux_total; - maa_mux_t mux[6]; + unsigned int pinmap; /**< sysfs pin */ + unsigned int parent_id; /** parent chip id */ + unsigned int mux_total; /** Numfer of muxes needed for operation of pin */ + maa_mux_t mux[6]; /** Array holding information about mux */ /*@}*/ } maa_pin_t; +typedef struct { + /*@{*/ + char mem_dev[32]; /**< Memory device to use /dev/uio0 etc */ + unsigned int mem_sz; /** Size of memory to map */ + unsigned int bit_pos; /** Position of value bit */ + maa_pin_t gpio; /** GPio context containing none mmap info */ + /*@}*/ +} maa_mmap_pin_t; + /** * A Structure representing a physical Pin. */ @@ -120,7 +129,7 @@ typedef struct { maa_pin_t gpio; /**< GPIO structure */ maa_pin_t pwm; /**< PWM structure */ maa_pin_t aio; /**< Anaglog Pin */ - maa_pin_t fast_gpio; /**< Fast GPIO */ + maa_mmap_pin_t mmap; /**< GPIO through memory */ maa_pin_t i2c; /**< i2c bus/pin */ maa_pin_t spi; /**< spi bus/pin */ /*@}*/ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index daea4db..d2ea271 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable (analogin_a0 analogin_a0.c) add_executable (isr_pin6 isr_pin6.c) add_executable (gpio_read6 gpio_read6.c) add_executable (spi_mcp4261 spi_mcp4261.c) +add_executable (mmap-io2 mmap-io2.c) include_directories(${PROJECT_SOURCE_DIR}/api) @@ -17,6 +18,7 @@ target_link_libraries (analogin_a0 maa) target_link_libraries (isr_pin6 maa) target_link_libraries (gpio_read6 maa) target_link_libraries (spi_mcp4261 maa) +target_link_libraries (mmap-io2 maa) add_subdirectory (c++) diff --git a/examples/mmap-io2.c b/examples/mmap-io2.c new file mode 100644 index 0000000..f1516ee --- /dev/null +++ b/examples/mmap-io2.c @@ -0,0 +1,47 @@ +/* + * Author: Thomas Ingleby + * Copyright (c) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "stdio.h" +#include + +#include "gpio.h" + +int +main(int argc, char **argv) +{ +//! [Interesting] + fprintf(stdout, "hello maa\n Version: %s\n", maa_get_version()); + maa_gpio_context gpio; + gpio = maa_gpio_init(2); + + maa_gpio_use_mmaped(gpio, 1); + + for (;;) { + maa_gpio_write(gpio , 1); + usleep(50000); + maa_gpio_write(gpio, 0); + usleep(50000); + } +//! [Interesting] +} diff --git a/include/maa_internal.h b/include/maa_internal.h index 428132d..042950e 100644 --- a/include/maa_internal.h +++ b/include/maa_internal.h @@ -62,3 +62,10 @@ maa_spi_bus_t* maa_setup_spi(int bus); * @return the pwm pin_info_t of that IO pin */ maa_pin_t* maa_setup_pwm(int pin); + +/** Setup gpio mux to go straight to SoC, galileo. + * + * @param pin physical pin to use + * @return maa_mmap_pin_t + */ +maa_mmap_pin_t* maa_setup_mmap_gpio(int pin); diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index c3a80e9..6ee7448 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -33,6 +33,7 @@ #include #include #include +#include #define SYSFS_CLASS_GPIO "/sys/class/gpio" #define MAX_SIZE 64 @@ -45,11 +46,16 @@ struct _gpio { /*@{*/ int pin; /**< the pin number, as known to the os. */ + int phy_pin; /**< pin passed to clean init. -1 none and raw*/ int value_fp; /**< the file pointer to the value of the gpio */ void (* isr)(); /**< the interupt service request */ pthread_t thread_id; /**< the isr handler thread id */ int isr_value_fp; /**< the isr file pointer on the value */ maa_boolean_t owner; /**< If this context originally exported the pin */ + maa_boolean_t mmap; + void *reg; + unsigned int reg_sz; + unsigned int reg_bit_pos; /*@}*/ }; @@ -73,7 +79,9 @@ maa_gpio_init(int pin) if (pinm < 0) return NULL; - return maa_gpio_init_raw(pinm); + maa_gpio_context r = maa_gpio_init_raw(pinm); + r->phy_pin = pin; + return r; } maa_gpio_context @@ -90,12 +98,13 @@ maa_gpio_init_raw(int pin) dev->value_fp = -1; dev->isr_value_fp = -1; dev->pin = pin; + dev->phy_pin = -1; char directory[MAX_SIZE]; snprintf(directory, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/", dev->pin); struct stat dir; if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) { - fprintf(stderr, "GPIO Pin already exporting, continuing.\n"); + //fprintf(stderr, "GPIO Pin already exporting, continuing.\n"); dev->owner = 0; // Not Owner } else { int export = open(SYSFS_CLASS_GPIO "/export", O_WRONLY); @@ -115,6 +124,17 @@ maa_gpio_init_raw(int pin) return dev; } +static maa_result_t +maa_gpio_write_register(maa_gpio_context dev,int value) +{ + if (value == 1) { + *((unsigned *)dev->reg) |= (1<reg_bit_pos); + return MAA_SUCCESS; + } + *((unsigned *)dev->reg) &= ~(1<reg_bit_pos); + return MAA_SUCCESS; +} + static maa_result_t maa_gpio_wait_interrupt(int fd) { @@ -395,6 +415,9 @@ maa_gpio_read(maa_gpio_context dev) maa_result_t maa_gpio_write(maa_gpio_context dev, int value) { + if (dev->mmap == 1) + return maa_gpio_write_register(dev,value); + if (dev->value_fp == -1) { maa_gpio_get_valfp(dev); } @@ -461,3 +484,45 @@ maa_gpio_owner(maa_gpio_context dev, maa_boolean_t own) return MAA_SUCCESS; } +maa_result_t +maa_gpio_use_mmaped(maa_gpio_context dev, maa_boolean_t mmap_en) +{ + if (dev == NULL) { + return MAA_ERROR_INVALID_RESOURCE; + } + + if (maa_pin_mode_test(dev->phy_pin, MAA_PIN_FAST_GPIO) == 0) + return MAA_ERROR_NO_RESOURCES; + + maa_mmap_pin_t *mmp = maa_setup_mmap_gpio(dev->phy_pin); + if (mmp == NULL) + return MAA_ERROR_INVALID_RESOURCE; + + if (mmap_en == 1) { + if (dev->mmap == 0) { + close(dev->value_fp); + int fd; + fd = open(mmp->mem_dev, O_RDWR); + if (fd < 1) { + fprintf(stderr, "Unable to open memory device\n"); + return MAA_ERROR_INVALID_RESOURCE; + } + dev->reg_sz = mmp->mem_sz; + dev->reg = mmap(NULL, dev->reg_sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + dev->reg_bit_pos = mmp->bit_pos; + dev->mmap = 1; + return MAA_SUCCESS; + } + return MAA_ERROR_INVALID_PARAMETER; + } + + if (mmap_en == 0) { + if (dev ->mmap == 1) { + munmap(dev->reg, dev->reg_sz); + dev->mmap = 0; + } + return MAA_ERROR_INVALID_PARAMETER; + } + + return MAA_SUCCESS; +} diff --git a/src/intel_galileo_rev_d.c b/src/intel_galileo_rev_d.c index 9dc4dd9..69cdd27 100644 --- a/src/intel_galileo_rev_d.c +++ b/src/intel_galileo_rev_d.c @@ -62,6 +62,15 @@ maa_intel_galileo_rev_d() b->pins[2].gpio.mux_total = 1; b->pins[2].gpio.mux[0].pin = 31; b->pins[2].gpio.mux[0].value = 1; + b->pins[2].mmap.gpio.pinmap = 14; + strncpy(b->pins[2].mmap.mem_dev, "/dev/uio0", 12); + b->pins[2].mmap.gpio.mux_total = 2; + b->pins[2].mmap.gpio.mux[0].pin = 31; + b->pins[2].mmap.gpio.mux[0].value = 0; + b->pins[2].mmap.gpio.mux[1].pin = 14; + b->pins[2].mmap.gpio.mux[1].value = 0; + b->pins[2].mmap.mem_sz = 0x1000; + b->pins[2].mmap.bit_pos = 6; strncpy(b->pins[3].name, "IO3", 8); b->pins[3].capabilites = (maa_pincapabilities_t) {1,1,1,1,0,0,0}; @@ -69,10 +78,15 @@ maa_intel_galileo_rev_d() b->pins[3].gpio.mux_total = 1; b->pins[3].gpio.mux[0].pin = 30; b->pins[3].gpio.mux[0].value = 1; - b->pins[3].fast_gpio.pinmap = 15; - b->pins[3].fast_gpio.mux_total = 1; - b->pins[3].fast_gpio.mux[0].pin = 30; - b->pins[3].fast_gpio.mux[0].value = 0; + b->pins[3].mmap.gpio.pinmap = 15; + strncpy(b->pins[3].mmap.mem_dev, "/dev/uio0", 12); + b->pins[3].mmap.gpio.mux_total = 2; + b->pins[3].mmap.gpio.mux[0].pin = 30; + b->pins[3].mmap.gpio.mux[0].value = 0; + b->pins[3].mmap.gpio.mux[1].pin = 15; + b->pins[3].mmap.gpio.mux[1].value = 0; + b->pins[3].mmap.mem_sz = 0x1000; + b->pins[3].mmap.bit_pos = 7; b->pins[3].pwm.pinmap = 3; b->pins[3].pwm.parent_id = 0; b->pins[3].pwm.mux_total = 1; diff --git a/src/maa.c b/src/maa.c index 0170564..0757356 100644 --- a/src/maa.c +++ b/src/maa.c @@ -312,3 +312,22 @@ maa_pin_mode_test(int pin, maa_pinmodes_t mode) } return 0; } + +maa_mmap_pin_t* +maa_setup_mmap_gpio(int pin) +{ + if (plat == NULL) + return NULL; + + if (plat->pins[pin].capabilites.fast_gpio != 1) + return NULL; + + if (plat->pins[pin].mmap.gpio.mux_total > 0) + if (maa_setup_mux_mapped(plat->pins[pin].mmap.gpio) != MAA_SUCCESS) + return NULL; + + if (maa_setup_mux_mapped(plat->pins[pin].mmap.gpio) != MAA_SUCCESS) + return NULL; + maa_mmap_pin_t *ret = &(plat->pins[pin].mmap); + return ret; +}