summaryrefslogtreecommitdiffstats
path: root/cpukit/dev
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-11-07 13:50:01 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-11-20 10:30:12 +0100
commit67ac69fc3f9b47af19df3176317adc5a6cb5d4fa (patch)
tree217463a9b8ba518c5962fbbf3c4bd4d5b480b70d /cpukit/dev
parentAdd generic EEPROM I2C device driver (diff)
downloadrtems-67ac69fc3f9b47af19df3176317adc5a6cb5d4fa.tar.bz2
Add NXP PCA9535 16-bit GPIO I2C driver
Diffstat (limited to 'cpukit/dev')
-rw-r--r--cpukit/dev/Makefile.am2
-rw-r--r--cpukit/dev/i2c/gpio-nxp-pca9535.c149
-rw-r--r--cpukit/dev/include/dev/i2c/gpio-nxp-pca9535.h123
-rw-r--r--cpukit/dev/preinstall.am4
4 files changed, 278 insertions, 0 deletions
diff --git a/cpukit/dev/Makefile.am b/cpukit/dev/Makefile.am
index f782da22fb..93737f987a 100644
--- a/cpukit/dev/Makefile.am
+++ b/cpukit/dev/Makefile.am
@@ -7,6 +7,7 @@ include_dev_HEADERS =
include_dev_i2cdir = $(includedir)/dev/i2c
include_dev_i2c_HEADERS =
include_dev_i2c_HEADERS += include/dev/i2c/eeprom.h
+include_dev_i2c_HEADERS += include/dev/i2c/gpio-nxp-pca9535.h
include_dev_i2c_HEADERS += include/dev/i2c/i2c.h
include_linuxdir = $(includedir)/linux
@@ -18,6 +19,7 @@ noinst_LIBRARIES = libdev.a
libdev_a_SOURCES =
libdev_a_SOURCES += i2c/eeprom.c
+libdev_a_SOURCES += i2c/gpio-nxp-pca9535.c
libdev_a_SOURCES += i2c/i2c-bus.c
libdev_a_SOURCES += i2c/i2c-dev.c
diff --git a/cpukit/dev/i2c/gpio-nxp-pca9535.c b/cpukit/dev/i2c/gpio-nxp-pca9535.c
new file mode 100644
index 0000000000..65df969e56
--- /dev/null
+++ b/cpukit/dev/i2c/gpio-nxp-pca9535.c
@@ -0,0 +1,149 @@
+/**
+ * @file
+ *
+ * @brief GPIO NXP PCA9535 Driver Implementation
+ *
+ * @ingroup I2CGPIONXPPCA9535
+ */
+
+/*
+ * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <dev/i2c/gpio-nxp-pca9535.h>
+
+typedef enum {
+ GPIO_NXP_PCA9535_INPUT_PORT_0,
+ GPIO_NXP_PCA9535_INPUT_PORT_1,
+ GPIO_NXP_PCA9535_OUTPUT_PORT_0,
+ GPIO_NXP_PCA9535_OUTPUT_PORT_1,
+ GPIO_NXP_PCA9535_POL_INV_PORT_0,
+ GPIO_NXP_PCA9535_POL_INV_PORT_1,
+ GPIO_NXP_PCA9535_CONF_PORT_0,
+ GPIO_NXP_PCA9535_CONF_PORT_1
+} gpio_nxp_pca9535_port;
+
+static int gpio_nxp_pca9535_get_reg(
+ i2c_dev *dev,
+ gpio_nxp_pca9535_port port,
+ uint16_t *val
+)
+{
+ uint8_t buf[1] = { port };
+ i2c_msg msgs[2] = {
+ {
+ .addr = dev->address,
+ .flags = 0,
+ .len = (uint16_t) sizeof(buf),
+ .buf = &buf[0]
+ }, {
+ .addr = dev->address,
+ .flags = I2C_M_RD,
+ .len = (uint16_t) sizeof(*val),
+ .buf = (uint8_t *) val
+ }
+ };
+
+ return i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
+}
+
+static int gpio_nxp_pca9535_set_reg(
+ i2c_dev *dev,
+ gpio_nxp_pca9535_port port,
+ uint16_t val
+)
+{
+ uint8_t buf[3] = { port, (uint8_t) val, (uint8_t) (val >> 8) };
+ i2c_msg msgs[1] = {
+ {
+ .addr = dev->address,
+ .flags = 0,
+ .len = (uint16_t) sizeof(buf),
+ .buf = &buf[0]
+ }
+ };
+
+ return i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
+}
+
+static int gpio_nxp_pca9535_ioctl(
+ i2c_dev *dev,
+ ioctl_command_t command,
+ void *arg
+)
+{
+ uint16_t v16 = (uint16_t)(uintptr_t) arg;
+ uint32_t v32 = (uint32_t)(uintptr_t) arg;
+ int err;
+
+ switch (command) {
+ case GPIO_NXP_PCA9535_GET_INPUT:
+ err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_INPUT_PORT_0, arg);
+ break;
+ case GPIO_NXP_PCA9535_GET_OUTPUT:
+ err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, arg);
+ break;
+ case GPIO_NXP_PCA9535_CLEAR_AND_SET_OUTPUT:
+ i2c_bus_obtain(dev->bus);
+ err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, &v16);
+ if (err == 0) {
+ v16 &= ~((uint16_t) v32);
+ v16 |= (uint16_t) (v32 >> 16);
+ err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, v16);
+ }
+ i2c_bus_release(dev->bus);
+ break;
+ case GPIO_NXP_PCA9535_SET_OUTPUT:
+ err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, v16);
+ break;
+ case GPIO_NXP_PCA9535_GET_POL_INV:
+ err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_POL_INV_PORT_0, arg);
+ break;
+ case GPIO_NXP_PCA9535_SET_POL_INV:
+ err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_POL_INV_PORT_0, v16);
+ break;
+ case GPIO_NXP_PCA9535_GET_CONFIG:
+ err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_CONF_PORT_0, arg);
+ break;
+ case GPIO_NXP_PCA9535_SET_CONFIG:
+ err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_CONF_PORT_0, v16);
+ break;
+ default:
+ err = -ENOTTY;
+ break;
+ }
+
+ return err;
+}
+
+int i2c_dev_register_gpio_nxp_pca9535(
+ const char *bus_path,
+ const char *dev_path,
+ uint16_t address
+)
+{
+ i2c_dev *dev;
+
+ dev = i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address);
+ if (dev == NULL) {
+ return -1;
+ }
+
+ dev->ioctl = gpio_nxp_pca9535_ioctl;
+
+ return i2c_dev_register(dev, dev_path);
+}
diff --git a/cpukit/dev/include/dev/i2c/gpio-nxp-pca9535.h b/cpukit/dev/include/dev/i2c/gpio-nxp-pca9535.h
new file mode 100644
index 0000000000..1ebc1a3d4d
--- /dev/null
+++ b/cpukit/dev/include/dev/i2c/gpio-nxp-pca9535.h
@@ -0,0 +1,123 @@
+/**
+ * @file
+ *
+ * @brief GPIO NXP PCA9535 Driver API
+ *
+ * @ingroup I2CGPIONXPPCA9535
+ */
+
+/*
+ * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef _DEV_I2C_GPIO_NXP_PCA9539_H
+#define _DEV_I2C_GPIO_NXP_PCA9539_H
+
+#include <dev/i2c/i2c.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup I2CGPIONXPPCA9535 GPIO NXP PCA9535 Driver
+ *
+ * @ingroup I2CDevice
+ *
+ * @brief Driver for NXP PCA9535 16-bit GPIO device.
+ *
+ * @{
+ */
+
+int i2c_dev_register_gpio_nxp_pca9535(
+ const char *bus_path,
+ const char *dev_path,
+ uint16_t address
+);
+
+#define GPIO_NXP_PCA9535_GET_INPUT (I2C_DEV_IO_CONTROL + 0)
+
+#define GPIO_NXP_PCA9535_GET_OUTPUT (I2C_DEV_IO_CONTROL + 1)
+
+#define GPIO_NXP_PCA9535_SET_OUTPUT (I2C_DEV_IO_CONTROL + 2)
+
+#define GPIO_NXP_PCA9535_CLEAR_AND_SET_OUTPUT (I2C_DEV_IO_CONTROL + 3)
+
+#define GPIO_NXP_PCA9535_GET_POL_INV (I2C_DEV_IO_CONTROL + 4)
+
+#define GPIO_NXP_PCA9535_SET_POL_INV (I2C_DEV_IO_CONTROL + 5)
+
+#define GPIO_NXP_PCA9535_GET_CONFIG (I2C_DEV_IO_CONTROL + 6)
+
+#define GPIO_NXP_PCA9535_SET_CONFIG (I2C_DEV_IO_CONTROL + 7)
+
+static inline int gpio_nxp_pca9535_get_input(int fd, uint16_t *val)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_GET_INPUT, val);
+}
+
+static inline int gpio_nxp_pca9535_get_output(int fd, uint16_t *val)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_GET_OUTPUT, val);
+}
+
+static inline int gpio_nxp_pca9535_set_output(int fd, uint16_t val)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_SET_OUTPUT, (void *)(uintptr_t) val);
+}
+
+static inline int gpio_nxp_pca9535_clear_and_set_output(
+ int fd,
+ uint16_t clear,
+ uint16_t set
+)
+{
+ uint32_t clear_and_set = ((uint32_t) set << 16) | (uint32_t) clear;
+
+ return ioctl(
+ fd,
+ GPIO_NXP_PCA9535_CLEAR_AND_SET_OUTPUT,
+ (void *)(uintptr_t) clear_and_set
+ );
+}
+
+static inline int gpio_nxp_pca9535_get_polarity_inversion(
+ int fd,
+ uint16_t *val
+)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_GET_POL_INV, val);
+}
+
+static inline int gpio_nxp_pca9535_set_polarity_inversion(int fd, uint16_t val)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_SET_POL_INV, (void *)(uintptr_t) val);
+}
+
+static inline int gpio_nxp_pca9535_get_config(int fd, uint16_t *val)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_GET_CONFIG, val);
+}
+
+static inline int gpio_nxp_pca9535_set_config(int fd, uint16_t val)
+{
+ return ioctl(fd, GPIO_NXP_PCA9535_SET_CONFIG, (void *)(uintptr_t) val);
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _DEV_I2C_GPIO_NXP_PCA9539_H */
diff --git a/cpukit/dev/preinstall.am b/cpukit/dev/preinstall.am
index 4472b810dc..28e361b5e5 100644
--- a/cpukit/dev/preinstall.am
+++ b/cpukit/dev/preinstall.am
@@ -27,6 +27,10 @@ $(PROJECT_INCLUDE)/dev/i2c/eeprom.h: include/dev/i2c/eeprom.h $(PROJECT_INCLUDE)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/eeprom.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/eeprom.h
+$(PROJECT_INCLUDE)/dev/i2c/gpio-nxp-pca9535.h: include/dev/i2c/gpio-nxp-pca9535.h $(PROJECT_INCLUDE)/dev/i2c/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/gpio-nxp-pca9535.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/gpio-nxp-pca9535.h
+
$(PROJECT_INCLUDE)/dev/i2c/i2c.h: include/dev/i2c/i2c.h $(PROJECT_INCLUDE)/dev/i2c/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/i2c.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/i2c.h