1*486cad03SDirk Eibach /* 2*486cad03SDirk Eibach * (C) Copyright 2011 3*486cad03SDirk Eibach * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de 4*486cad03SDirk Eibach * 5*486cad03SDirk Eibach * See file CREDITS for list of people who contributed to this 6*486cad03SDirk Eibach * project. 7*486cad03SDirk Eibach * 8*486cad03SDirk Eibach * This program is free software; you can redistribute it and/or 9*486cad03SDirk Eibach * modify it under the terms of the GNU General Public License as 10*486cad03SDirk Eibach * published by the Free Software Foundation; either version 2 of 11*486cad03SDirk Eibach * the License, or (at your option) any later version. 12*486cad03SDirk Eibach * 13*486cad03SDirk Eibach * This program is distributed in the hope that it will be useful, 14*486cad03SDirk Eibach * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*486cad03SDirk Eibach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*486cad03SDirk Eibach * GNU General Public License for more details. 17*486cad03SDirk Eibach * 18*486cad03SDirk Eibach * You should have received a copy of the GNU General Public License 19*486cad03SDirk Eibach * along with this program; if not, write to the Free Software 20*486cad03SDirk Eibach * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*486cad03SDirk Eibach * MA 02111-1307 USA 22*486cad03SDirk Eibach */ 23*486cad03SDirk Eibach 24*486cad03SDirk Eibach /* 25*486cad03SDirk Eibach * Driver for NXP's pca9698 40 bit I2C gpio expander 26*486cad03SDirk Eibach */ 27*486cad03SDirk Eibach 28*486cad03SDirk Eibach #include <common.h> 29*486cad03SDirk Eibach #include <i2c.h> 30*486cad03SDirk Eibach #include <pca9698.h> 31*486cad03SDirk Eibach 32*486cad03SDirk Eibach /* 33*486cad03SDirk Eibach * The pca9698 registers 34*486cad03SDirk Eibach */ 35*486cad03SDirk Eibach 36*486cad03SDirk Eibach #define PCA9698_REG_INPUT 0x00 37*486cad03SDirk Eibach #define PCA9698_REG_OUTPUT 0x08 38*486cad03SDirk Eibach #define PCA9698_REG_POLARITY 0x10 39*486cad03SDirk Eibach #define PCA9698_REG_CONFIG 0x18 40*486cad03SDirk Eibach 41*486cad03SDirk Eibach #define PCA9698_BUFFER_SIZE 5 42*486cad03SDirk Eibach 43*486cad03SDirk Eibach static int pca9698_read40(u8 chip, u8 offset, u8 *buffer) 44*486cad03SDirk Eibach { 45*486cad03SDirk Eibach u8 command = offset | 0x80; /* autoincrement */ 46*486cad03SDirk Eibach 47*486cad03SDirk Eibach return i2c_read(chip, command, 1, buffer, PCA9698_BUFFER_SIZE); 48*486cad03SDirk Eibach } 49*486cad03SDirk Eibach 50*486cad03SDirk Eibach static int pca9698_write40(u8 chip, u8 offset, u8 *buffer) 51*486cad03SDirk Eibach { 52*486cad03SDirk Eibach u8 command = offset | 0x80; /* autoincrement */ 53*486cad03SDirk Eibach 54*486cad03SDirk Eibach return i2c_write(chip, command, 1, buffer, PCA9698_BUFFER_SIZE); 55*486cad03SDirk Eibach } 56*486cad03SDirk Eibach 57*486cad03SDirk Eibach static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value) 58*486cad03SDirk Eibach { 59*486cad03SDirk Eibach unsigned byte = gpio / 8; 60*486cad03SDirk Eibach unsigned bit = gpio % 8; 61*486cad03SDirk Eibach 62*486cad03SDirk Eibach if (value) 63*486cad03SDirk Eibach buffer[byte] |= (1 << bit); 64*486cad03SDirk Eibach else 65*486cad03SDirk Eibach buffer[byte] &= ~(1 << bit); 66*486cad03SDirk Eibach } 67*486cad03SDirk Eibach 68*486cad03SDirk Eibach int pca9698_direction_input(u8 chip, unsigned offset) 69*486cad03SDirk Eibach { 70*486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 71*486cad03SDirk Eibach int res; 72*486cad03SDirk Eibach 73*486cad03SDirk Eibach res = pca9698_read40(chip, PCA9698_REG_CONFIG, data); 74*486cad03SDirk Eibach if (res) 75*486cad03SDirk Eibach return res; 76*486cad03SDirk Eibach 77*486cad03SDirk Eibach pca9698_set_bit(offset, data, 1); 78*486cad03SDirk Eibach return pca9698_write40(chip, PCA9698_REG_CONFIG, data); 79*486cad03SDirk Eibach } 80*486cad03SDirk Eibach 81*486cad03SDirk Eibach int pca9698_direction_output(u8 chip, unsigned offset) 82*486cad03SDirk Eibach { 83*486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 84*486cad03SDirk Eibach int res; 85*486cad03SDirk Eibach 86*486cad03SDirk Eibach res = pca9698_read40(chip, PCA9698_REG_CONFIG, data); 87*486cad03SDirk Eibach if (res) 88*486cad03SDirk Eibach return res; 89*486cad03SDirk Eibach 90*486cad03SDirk Eibach pca9698_set_bit(offset, data, 0); 91*486cad03SDirk Eibach return pca9698_write40(chip, PCA9698_REG_CONFIG, data); 92*486cad03SDirk Eibach } 93*486cad03SDirk Eibach 94*486cad03SDirk Eibach int pca9698_get_input(u8 chip, unsigned offset) 95*486cad03SDirk Eibach { 96*486cad03SDirk Eibach unsigned config_byte = offset / 8; 97*486cad03SDirk Eibach unsigned config_bit = offset % 8; 98*486cad03SDirk Eibach unsigned value; 99*486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 100*486cad03SDirk Eibach int res; 101*486cad03SDirk Eibach 102*486cad03SDirk Eibach res = pca9698_read40(chip, PCA9698_REG_INPUT, data); 103*486cad03SDirk Eibach if (res) 104*486cad03SDirk Eibach return -1; 105*486cad03SDirk Eibach 106*486cad03SDirk Eibach value = data[config_byte] & (1 << config_bit); 107*486cad03SDirk Eibach 108*486cad03SDirk Eibach return !!value; 109*486cad03SDirk Eibach } 110*486cad03SDirk Eibach 111*486cad03SDirk Eibach int pca9698_set_output(u8 chip, unsigned offset, int value) 112*486cad03SDirk Eibach { 113*486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 114*486cad03SDirk Eibach int res; 115*486cad03SDirk Eibach 116*486cad03SDirk Eibach res = pca9698_read40(chip, PCA9698_REG_OUTPUT, data); 117*486cad03SDirk Eibach if (res) 118*486cad03SDirk Eibach return res; 119*486cad03SDirk Eibach 120*486cad03SDirk Eibach memset(data, sizeof(data), 0); 121*486cad03SDirk Eibach pca9698_set_bit(offset, data, value); 122*486cad03SDirk Eibach return pca9698_write40(chip, PCA9698_REG_OUTPUT, data); 123*486cad03SDirk Eibach } 124