1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2011 4 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach (at) gdsys.cc 5 */ 6 7 /* 8 * Driver for NXP's pca9698 40 bit I2C gpio expander 9 */ 10 11 #include <common.h> 12 #include <i2c.h> 13 #include <linux/errno.h> 14 #include <pca9698.h> 15 16 /* 17 * The pca9698 registers 18 */ 19 20 #define PCA9698_REG_INPUT 0x00 21 #define PCA9698_REG_OUTPUT 0x08 22 #define PCA9698_REG_POLARITY 0x10 23 #define PCA9698_REG_CONFIG 0x18 24 25 #define PCA9698_BUFFER_SIZE 5 26 #define PCA9698_GPIO_COUNT 40 27 28 static int pca9698_read40(u8 addr, u8 offset, u8 *buffer) 29 { 30 u8 command = offset | 0x80; /* autoincrement */ 31 32 return i2c_read(addr, command, 1, buffer, PCA9698_BUFFER_SIZE); 33 } 34 35 static int pca9698_write40(u8 addr, u8 offset, u8 *buffer) 36 { 37 u8 command = offset | 0x80; /* autoincrement */ 38 39 return i2c_write(addr, command, 1, buffer, PCA9698_BUFFER_SIZE); 40 } 41 42 static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value) 43 { 44 unsigned byte = gpio / 8; 45 unsigned bit = gpio % 8; 46 47 if (value) 48 buffer[byte] |= (1 << bit); 49 else 50 buffer[byte] &= ~(1 << bit); 51 } 52 53 int pca9698_request(unsigned gpio, const char *label) 54 { 55 if (gpio >= PCA9698_GPIO_COUNT) 56 return -EINVAL; 57 58 return 0; 59 } 60 61 void pca9698_free(unsigned gpio) 62 { 63 } 64 65 int pca9698_direction_input(u8 addr, unsigned gpio) 66 { 67 u8 data[PCA9698_BUFFER_SIZE]; 68 int res; 69 70 res = pca9698_read40(addr, PCA9698_REG_CONFIG, data); 71 if (res) 72 return res; 73 74 pca9698_set_bit(gpio, data, 1); 75 76 return pca9698_write40(addr, PCA9698_REG_CONFIG, data); 77 } 78 79 int pca9698_direction_output(u8 addr, unsigned gpio, int value) 80 { 81 u8 data[PCA9698_BUFFER_SIZE]; 82 int res; 83 84 res = pca9698_set_value(addr, gpio, value); 85 if (res) 86 return res; 87 88 res = pca9698_read40(addr, PCA9698_REG_CONFIG, data); 89 if (res) 90 return res; 91 92 pca9698_set_bit(gpio, data, 0); 93 94 return pca9698_write40(addr, PCA9698_REG_CONFIG, data); 95 } 96 97 int pca9698_get_value(u8 addr, unsigned gpio) 98 { 99 unsigned config_byte = gpio / 8; 100 unsigned config_bit = gpio % 8; 101 unsigned value; 102 u8 data[PCA9698_BUFFER_SIZE]; 103 int res; 104 105 res = pca9698_read40(addr, PCA9698_REG_INPUT, data); 106 if (res) 107 return -1; 108 109 value = data[config_byte] & (1 << config_bit); 110 111 return !!value; 112 } 113 114 int pca9698_set_value(u8 addr, unsigned gpio, int value) 115 { 116 u8 data[PCA9698_BUFFER_SIZE]; 117 int res; 118 119 res = pca9698_read40(addr, PCA9698_REG_OUTPUT, data); 120 if (res) 121 return res; 122 123 pca9698_set_bit(gpio, data, value); 124 125 return pca9698_write40(addr, PCA9698_REG_OUTPUT, data); 126 } 127