File indexing completed on 2025-05-11 08:24:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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 }