xref: /openbmc/u-boot/drivers/gpio/pca9698.c (revision 486cad03)
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