From 67ac69fc3f9b47af19df3176317adc5a6cb5d4fa Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 7 Nov 2014 13:50:01 +0100 Subject: Add NXP PCA9535 16-bit GPIO I2C driver --- cpukit/dev/Makefile.am | 2 + cpukit/dev/i2c/gpio-nxp-pca9535.c | 149 ++++++++++++++++++++++++++ cpukit/dev/include/dev/i2c/gpio-nxp-pca9535.h | 123 +++++++++++++++++++++ cpukit/dev/preinstall.am | 4 + 4 files changed, 278 insertions(+) create mode 100644 cpukit/dev/i2c/gpio-nxp-pca9535.c create mode 100644 cpukit/dev/include/dev/i2c/gpio-nxp-pca9535.h (limited to 'cpukit/dev') 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 + * + * + * 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 + +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 + * + * + * 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 + +#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 -- cgit v1.2.3