1486cad03SDirk Eibach /* 2486cad03SDirk Eibach * (C) Copyright 2011 3486cad03SDirk Eibach * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de 4486cad03SDirk Eibach * 5486cad03SDirk Eibach * See file CREDITS for list of people who contributed to this 6486cad03SDirk Eibach * project. 7486cad03SDirk Eibach * 8486cad03SDirk Eibach * This program is free software; you can redistribute it and/or 9486cad03SDirk Eibach * modify it under the terms of the GNU General Public License as 10486cad03SDirk Eibach * published by the Free Software Foundation; either version 2 of 11486cad03SDirk Eibach * the License, or (at your option) any later version. 12486cad03SDirk Eibach * 13486cad03SDirk Eibach * This program is distributed in the hope that it will be useful, 14486cad03SDirk Eibach * but WITHOUT ANY WARRANTY; without even the implied warranty of 15486cad03SDirk Eibach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16486cad03SDirk Eibach * GNU General Public License for more details. 17486cad03SDirk Eibach * 18486cad03SDirk Eibach * You should have received a copy of the GNU General Public License 19486cad03SDirk Eibach * along with this program; if not, write to the Free Software 20486cad03SDirk Eibach * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21486cad03SDirk Eibach * MA 02111-1307 USA 22486cad03SDirk Eibach */ 23486cad03SDirk Eibach 24486cad03SDirk Eibach /* 25486cad03SDirk Eibach * Driver for NXP's pca9698 40 bit I2C gpio expander 26486cad03SDirk Eibach */ 27486cad03SDirk Eibach 28486cad03SDirk Eibach #include <common.h> 29486cad03SDirk Eibach #include <i2c.h> 30*042f9f10SDirk Eibach #include <asm/errno.h> 31486cad03SDirk Eibach #include <pca9698.h> 32486cad03SDirk Eibach 33486cad03SDirk Eibach /* 34486cad03SDirk Eibach * The pca9698 registers 35486cad03SDirk Eibach */ 36486cad03SDirk Eibach 37486cad03SDirk Eibach #define PCA9698_REG_INPUT 0x00 38486cad03SDirk Eibach #define PCA9698_REG_OUTPUT 0x08 39486cad03SDirk Eibach #define PCA9698_REG_POLARITY 0x10 40486cad03SDirk Eibach #define PCA9698_REG_CONFIG 0x18 41486cad03SDirk Eibach 42486cad03SDirk Eibach #define PCA9698_BUFFER_SIZE 5 43*042f9f10SDirk Eibach #define PCA9698_GPIO_COUNT 40 44486cad03SDirk Eibach 45*042f9f10SDirk Eibach static int pca9698_read40(u8 addr, u8 offset, u8 *buffer) 46486cad03SDirk Eibach { 47486cad03SDirk Eibach u8 command = offset | 0x80; /* autoincrement */ 48486cad03SDirk Eibach 49*042f9f10SDirk Eibach return i2c_read(addr, command, 1, buffer, PCA9698_BUFFER_SIZE); 50486cad03SDirk Eibach } 51486cad03SDirk Eibach 52*042f9f10SDirk Eibach static int pca9698_write40(u8 addr, u8 offset, u8 *buffer) 53486cad03SDirk Eibach { 54486cad03SDirk Eibach u8 command = offset | 0x80; /* autoincrement */ 55486cad03SDirk Eibach 56*042f9f10SDirk Eibach return i2c_write(addr, command, 1, buffer, PCA9698_BUFFER_SIZE); 57486cad03SDirk Eibach } 58486cad03SDirk Eibach 59486cad03SDirk Eibach static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value) 60486cad03SDirk Eibach { 61486cad03SDirk Eibach unsigned byte = gpio / 8; 62486cad03SDirk Eibach unsigned bit = gpio % 8; 63486cad03SDirk Eibach 64486cad03SDirk Eibach if (value) 65486cad03SDirk Eibach buffer[byte] |= (1 << bit); 66486cad03SDirk Eibach else 67486cad03SDirk Eibach buffer[byte] &= ~(1 << bit); 68486cad03SDirk Eibach } 69486cad03SDirk Eibach 70*042f9f10SDirk Eibach int pca9698_request(unsigned gpio, const char *label) 71*042f9f10SDirk Eibach { 72*042f9f10SDirk Eibach if (gpio >= PCA9698_GPIO_COUNT) 73*042f9f10SDirk Eibach return -EINVAL; 74*042f9f10SDirk Eibach 75*042f9f10SDirk Eibach return 0; 76*042f9f10SDirk Eibach } 77*042f9f10SDirk Eibach 78*042f9f10SDirk Eibach void pca9698_free(unsigned gpio) 79*042f9f10SDirk Eibach { 80*042f9f10SDirk Eibach } 81*042f9f10SDirk Eibach 82*042f9f10SDirk Eibach int pca9698_direction_input(u8 addr, unsigned gpio) 83486cad03SDirk Eibach { 84486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 85486cad03SDirk Eibach int res; 86486cad03SDirk Eibach 87*042f9f10SDirk Eibach res = pca9698_read40(addr, PCA9698_REG_CONFIG, data); 88486cad03SDirk Eibach if (res) 89486cad03SDirk Eibach return res; 90486cad03SDirk Eibach 91*042f9f10SDirk Eibach pca9698_set_bit(gpio, data, 1); 92*042f9f10SDirk Eibach 93*042f9f10SDirk Eibach return pca9698_write40(addr, PCA9698_REG_CONFIG, data); 94486cad03SDirk Eibach } 95486cad03SDirk Eibach 96*042f9f10SDirk Eibach int pca9698_direction_output(u8 addr, unsigned gpio, int value) 97486cad03SDirk Eibach { 98486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 99486cad03SDirk Eibach int res; 100486cad03SDirk Eibach 101*042f9f10SDirk Eibach res = pca9698_set_value(addr, gpio, value); 102486cad03SDirk Eibach if (res) 103486cad03SDirk Eibach return res; 104486cad03SDirk Eibach 105*042f9f10SDirk Eibach res = pca9698_read40(addr, PCA9698_REG_CONFIG, data); 106*042f9f10SDirk Eibach if (res) 107*042f9f10SDirk Eibach return res; 108*042f9f10SDirk Eibach 109*042f9f10SDirk Eibach pca9698_set_bit(gpio, data, 0); 110*042f9f10SDirk Eibach 111*042f9f10SDirk Eibach return pca9698_write40(addr, PCA9698_REG_CONFIG, data); 112486cad03SDirk Eibach } 113486cad03SDirk Eibach 114*042f9f10SDirk Eibach int pca9698_get_value(u8 addr, unsigned gpio) 115486cad03SDirk Eibach { 116*042f9f10SDirk Eibach unsigned config_byte = gpio / 8; 117*042f9f10SDirk Eibach unsigned config_bit = gpio % 8; 118486cad03SDirk Eibach unsigned value; 119486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 120486cad03SDirk Eibach int res; 121486cad03SDirk Eibach 122*042f9f10SDirk Eibach res = pca9698_read40(addr, PCA9698_REG_INPUT, data); 123486cad03SDirk Eibach if (res) 124486cad03SDirk Eibach return -1; 125486cad03SDirk Eibach 126486cad03SDirk Eibach value = data[config_byte] & (1 << config_bit); 127486cad03SDirk Eibach 128486cad03SDirk Eibach return !!value; 129486cad03SDirk Eibach } 130486cad03SDirk Eibach 131*042f9f10SDirk Eibach int pca9698_set_value(u8 addr, unsigned gpio, int value) 132486cad03SDirk Eibach { 133486cad03SDirk Eibach u8 data[PCA9698_BUFFER_SIZE]; 134486cad03SDirk Eibach int res; 135486cad03SDirk Eibach 136*042f9f10SDirk Eibach res = pca9698_read40(addr, PCA9698_REG_OUTPUT, data); 137486cad03SDirk Eibach if (res) 138486cad03SDirk Eibach return res; 139486cad03SDirk Eibach 140*042f9f10SDirk Eibach pca9698_set_bit(gpio, data, value); 141*042f9f10SDirk Eibach 142*042f9f10SDirk Eibach return pca9698_write40(addr, PCA9698_REG_OUTPUT, data); 143486cad03SDirk Eibach } 144