Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:11

0001 /**
0002  * @file
0003  *
0004  * @brief GPIO NXP PCA9535 Driver Implementation
0005  *
0006  * @ingroup I2CGPIONXPPCA9535
0007  */
0008 
0009 /*
0010  * Copyright (c) 2014 embedded brains GmbH & Co. KG
0011  *
0012  * The license and distribution terms for this file may be
0013  * found in the file LICENSE in this distribution or at
0014  * http://www.rtems.org/license/LICENSE.
0015  */
0016 
0017 #ifdef HAVE_CONFIG_H
0018 #include "config.h"
0019 #endif
0020 
0021 #include <dev/i2c/gpio-nxp-pca9535.h>
0022 
0023 typedef enum {
0024   GPIO_NXP_PCA9535_INPUT_PORT_0,
0025   GPIO_NXP_PCA9535_INPUT_PORT_1,
0026   GPIO_NXP_PCA9535_OUTPUT_PORT_0,
0027   GPIO_NXP_PCA9535_OUTPUT_PORT_1,
0028   GPIO_NXP_PCA9535_POL_INV_PORT_0,
0029   GPIO_NXP_PCA9535_POL_INV_PORT_1,
0030   GPIO_NXP_PCA9535_CONF_PORT_0,
0031   GPIO_NXP_PCA9535_CONF_PORT_1
0032 } gpio_nxp_pca9535_port;
0033 
0034 static int gpio_nxp_pca9535_get_reg(
0035   i2c_dev *dev,
0036   gpio_nxp_pca9535_port port,
0037   uint16_t *val
0038 )
0039 {
0040   uint8_t out[1] = { port };
0041   uint8_t in[sizeof(*val)];
0042   i2c_msg msgs[2] = {
0043     {
0044       .addr = dev->address,
0045       .flags = 0,
0046       .len = (uint16_t) sizeof(out),
0047       .buf = &out[0]
0048     }, {
0049       .addr = dev->address,
0050       .flags = I2C_M_RD,
0051       .len = (uint16_t) sizeof(in),
0052       .buf = &in[0]
0053     }
0054   };
0055   int err;
0056 
0057   err = i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
0058   *val = in[0] | (in[1] << 8);
0059 
0060   return err;
0061 }
0062 
0063 static int gpio_nxp_pca9535_set_reg(
0064   i2c_dev *dev,
0065   gpio_nxp_pca9535_port port,
0066   uint16_t val
0067 )
0068 {
0069   uint8_t out[3] = { port, (uint8_t) val, (uint8_t) (val >> 8) };
0070   i2c_msg msgs[1] = {
0071     {
0072       .addr = dev->address,
0073       .flags = 0,
0074       .len = (uint16_t) sizeof(out),
0075       .buf = &out[0]
0076     }
0077   };
0078 
0079   return i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
0080 }
0081 
0082 static int gpio_nxp_pca9535_ioctl(
0083   i2c_dev *dev,
0084   ioctl_command_t command,
0085   void *arg
0086 )
0087 {
0088   uint16_t v16 = (uint16_t)(uintptr_t) arg;
0089   uint32_t v32 = (uint32_t)(uintptr_t) arg;
0090   int err;
0091 
0092   switch (command) {
0093     case GPIO_NXP_PCA9535_GET_INPUT:
0094       err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_INPUT_PORT_0, arg);
0095       break;
0096     case GPIO_NXP_PCA9535_GET_OUTPUT:
0097       err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, arg);
0098       break;
0099     case GPIO_NXP_PCA9535_CLEAR_AND_SET_OUTPUT:
0100       i2c_bus_obtain(dev->bus);
0101       err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, &v16);
0102       if (err == 0) {
0103         v16 &= ~((uint16_t) v32);
0104         v16 |= (uint16_t) (v32 >> 16);
0105         err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, v16);
0106       }
0107       i2c_bus_release(dev->bus);
0108       break;
0109     case GPIO_NXP_PCA9535_SET_OUTPUT:
0110       err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_OUTPUT_PORT_0, v16);
0111       break;
0112     case GPIO_NXP_PCA9535_GET_POL_INV:
0113       err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_POL_INV_PORT_0, arg);
0114       break;
0115     case GPIO_NXP_PCA9535_SET_POL_INV:
0116       err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_POL_INV_PORT_0, v16);
0117       break;
0118     case GPIO_NXP_PCA9535_GET_CONFIG:
0119       err = gpio_nxp_pca9535_get_reg(dev, GPIO_NXP_PCA9535_CONF_PORT_0, arg);
0120       break;
0121     case GPIO_NXP_PCA9535_SET_CONFIG:
0122       err = gpio_nxp_pca9535_set_reg(dev, GPIO_NXP_PCA9535_CONF_PORT_0, v16);
0123       break;
0124     default:
0125       err = -ENOTTY;
0126       break;
0127   }
0128 
0129   return err;
0130 }
0131 
0132 int i2c_dev_register_gpio_nxp_pca9535(
0133   const char *bus_path,
0134   const char *dev_path,
0135   uint16_t address
0136 )
0137 {
0138   i2c_dev *dev;
0139 
0140   dev = i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address);
0141   if (dev == NULL) {
0142     return -1;
0143   }
0144 
0145   dev->ioctl = gpio_nxp_pca9535_ioctl;
0146 
0147   return i2c_dev_register(dev, dev_path);
0148 }