summaryrefslogtreecommitdiffstats
path: root/cpukit/dev/i2c
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/i2c
parentAdd generic EEPROM I2C device driver (diff)
downloadrtems-67ac69fc3f9b47af19df3176317adc5a6cb5d4fa.tar.bz2
Add NXP PCA9535 16-bit GPIO I2C driver
Diffstat (limited to 'cpukit/dev/i2c')
-rw-r--r--cpukit/dev/i2c/gpio-nxp-pca9535.c149
1 files changed, 149 insertions, 0 deletions
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);
+}