2 * Copyright 2013 Texas Instruments, Inc.
3 * Author: Dan Murphy <dmurphy@ti.com>
5 * Derived work from the pca953x.c driver
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 /* tca642x register address definitions */
28 struct tca642x_bank_info tca642x_regs
[] = {
32 .configuration_reg
= 0x0c },
36 .configuration_reg
= 0x0d },
40 .configuration_reg
= 0x0e },
44 * Modify masked bits in register
46 static int tca642x_reg_write(uchar chip
, uint8_t addr
,
47 uint8_t reg_bit
, uint8_t data
)
53 org_bus_num
= i2c_get_bus_num();
54 i2c_set_bus_num(CONFIG_SYS_I2C_TCA642X_BUS_NUM
);
56 if (i2c_read(chip
, addr
, 1, (uint8_t *)&valw
, 1)) {
57 printf("Could not read before writing\n");
64 ret
= i2c_write(chip
, addr
, 1, (u8
*)&valw
, 1);
67 i2c_set_bus_num(org_bus_num
);
71 static int tca642x_reg_read(uchar chip
, uint8_t addr
, uint8_t *data
)
77 org_bus_num
= i2c_get_bus_num();
78 i2c_set_bus_num(CONFIG_SYS_I2C_TCA642X_BUS_NUM
);
79 if (i2c_read(chip
, addr
, 1, (u8
*)&valw
, 1)) {
87 i2c_set_bus_num(org_bus_num
);
92 * Set output value of IO pins in 'reg_bit' to corresponding value in 'data'
95 int tca642x_set_val(uchar chip
, uint8_t gpio_bank
,
96 uint8_t reg_bit
, uint8_t data
)
98 uint8_t out_reg
= tca642x_regs
[gpio_bank
].output_reg
;
100 return tca642x_reg_write(chip
, out_reg
, reg_bit
, data
);
104 * Set read polarity of IO pins in 'reg_bit' to corresponding value in 'data'
105 * 0 = read pin value, 1 = read inverted pin value
107 int tca642x_set_pol(uchar chip
, uint8_t gpio_bank
,
108 uint8_t reg_bit
, uint8_t data
)
110 uint8_t pol_reg
= tca642x_regs
[gpio_bank
].polarity_reg
;
112 return tca642x_reg_write(chip
, pol_reg
, reg_bit
, data
);
116 * Set direction of IO pins in 'reg_bit' to corresponding value in 'data'
117 * 0 = output, 1 = input
119 int tca642x_set_dir(uchar chip
, uint8_t gpio_bank
,
120 uint8_t reg_bit
, uint8_t data
)
122 uint8_t config_reg
= tca642x_regs
[gpio_bank
].configuration_reg
;
124 return tca642x_reg_write(chip
, config_reg
, reg_bit
, data
);
128 * Read current logic level of all IO pins
130 int tca642x_get_val(uchar chip
, uint8_t gpio_bank
)
133 uint8_t in_reg
= tca642x_regs
[gpio_bank
].input_reg
;
135 if (tca642x_reg_read(chip
, in_reg
, &val
) < 0)
142 * Set the inital register states for the tca642x gpio expander
144 int tca642x_set_inital_state(uchar chip
, struct tca642x_bank_info init_data
[])
148 uint8_t polarity_reg
;
151 for (i
= 0; i
< 3; i
++) {
152 config_reg
= tca642x_regs
[i
].configuration_reg
;
153 ret
= tca642x_reg_write(chip
, config_reg
, 0xff,
154 init_data
[i
].configuration_reg
);
155 polarity_reg
= tca642x_regs
[i
].polarity_reg
;
156 ret
= tca642x_reg_write(chip
, polarity_reg
, 0xff,
157 init_data
[i
].polarity_reg
);
158 output_reg
= tca642x_regs
[i
].output_reg
;
159 ret
= tca642x_reg_write(chip
, output_reg
, 0xff,
160 init_data
[i
].output_reg
);
166 #ifdef CONFIG_CMD_TCA642X
168 * Display tca642x information
170 static int tca642x_info(uchar chip
)
175 printf("tca642x@ 0x%x (%d pins):\n", chip
, 24);
176 for (i
= 0; i
< 3; i
++) {
177 printf("Bank %i\n", i
);
178 if (tca642x_reg_read(chip
,
179 tca642x_regs
[i
].configuration_reg
,
182 printf("\tConfiguration: ");
183 for (j
= 7; j
>= 0; j
--)
184 printf("%c", data
& (1 << j
) ? 'i' : 'o');
187 if (tca642x_reg_read(chip
,
188 tca642x_regs
[i
].polarity_reg
, &data
) < 0)
190 printf("\tPolarity: ");
191 for (j
= 7; j
>= 0; j
--)
192 printf("%c", data
& (1 << j
) ? '1' : '0');
195 if (tca642x_reg_read(chip
,
196 tca642x_regs
[i
].input_reg
, &data
) < 0)
198 printf("\tInput value: ");
199 for (j
= 7; j
>= 0; j
--)
200 printf("%c", data
& (1 << j
) ? '1' : '0');
203 if (tca642x_reg_read(chip
,
204 tca642x_regs
[i
].output_reg
, &data
) < 0)
206 printf("\tOutput value: ");
207 for (j
= 7; j
>= 0; j
--)
208 printf("%c", data
& (1 << j
) ? '1' : '0');
215 cmd_tbl_t cmd_tca642x
[] = {
216 U_BOOT_CMD_MKENT(device
, 3, 0, (void *)TCA642X_CMD_DEVICE
, "", ""),
217 U_BOOT_CMD_MKENT(output
, 4, 0, (void *)TCA642X_CMD_OUTPUT
, "", ""),
218 U_BOOT_CMD_MKENT(input
, 3, 0, (void *)TCA642X_CMD_INPUT
, "", ""),
219 U_BOOT_CMD_MKENT(invert
, 4, 0, (void *)TCA642X_CMD_INVERT
, "", ""),
220 U_BOOT_CMD_MKENT(info
, 2, 0, (void *)TCA642X_CMD_INFO
, "", ""),
223 int do_tca642x(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
225 static uchar chip
= CONFIG_SYS_I2C_TCA642X_ADDR
;
226 int ret
= CMD_RET_USAGE
, val
;
227 uint8_t gpio_bank
= 0;
233 c
= find_cmd_tbl(argv
[1], cmd_tca642x
, ARRAY_SIZE(cmd_tca642x
));
235 /* All commands but "device" require 'maxargs' arguments */
237 !((argc
== (c
->maxargs
)) ||
238 (((int)c
->cmd
== TCA642X_CMD_DEVICE
) &&
239 (argc
== (c
->maxargs
- 1))))) {
240 return CMD_RET_USAGE
;
243 /* arg2 used as chip number or pin number */
245 ul_arg2
= simple_strtoul(argv
[2], NULL
, 10);
247 /* arg3 used as pin or invert value */
249 ul_arg3
= simple_strtoul(argv
[3], NULL
, 10) & 0x1;
252 } else if ((ul_arg2
>= 10) && (ul_arg2
<= 17)) {
254 } else if ((ul_arg2
>= 20) && (ul_arg2
<= 27)) {
257 printf("Requested pin is not available\n");
258 ret
= CMD_RET_FAILURE
;
263 switch ((int)c
->cmd
) {
264 case TCA642X_CMD_INFO
:
265 ret
= tca642x_info(chip
);
267 ret
= CMD_RET_FAILURE
;
270 case TCA642X_CMD_DEVICE
:
272 chip
= (uint8_t)ul_arg2
;
273 printf("Current device address: 0x%x\n", chip
);
274 ret
= CMD_RET_SUCCESS
;
277 case TCA642X_CMD_INPUT
:
278 bank_shift
= ul_arg2
- (gpio_bank
* 10);
279 ret
= tca642x_set_dir(chip
, gpio_bank
, (1 << bank_shift
),
280 TCA642X_DIR_IN
<< bank_shift
);
281 val
= (tca642x_get_val(chip
, gpio_bank
) &
282 (1 << bank_shift
)) != 0;
285 ret
= CMD_RET_FAILURE
;
287 printf("chip 0x%02x, pin 0x%lx = %d\n", chip
,
291 case TCA642X_CMD_OUTPUT
:
292 bank_shift
= ul_arg2
- (gpio_bank
* 10);
293 ret
= tca642x_set_dir(chip
, gpio_bank
, (1 << bank_shift
),
294 (TCA642X_DIR_OUT
<< bank_shift
));
296 ret
= tca642x_set_val(chip
,
297 gpio_bank
, (1 << bank_shift
),
298 (ul_arg3
<< bank_shift
));
300 ret
= CMD_RET_FAILURE
;
303 case TCA642X_CMD_INVERT
:
304 bank_shift
= ul_arg2
- (gpio_bank
* 10);
305 ret
= tca642x_set_pol(chip
, gpio_bank
, (1 << bank_shift
),
306 (ul_arg3
<< bank_shift
));
308 ret
= CMD_RET_FAILURE
;
312 if (ret
== CMD_RET_FAILURE
)
313 eprintf("Error talking to chip at 0x%x\n", chip
);
319 tca642x
, 5, 1, do_tca642x
,
320 "tca642x gpio access",
322 " - show or set current device address\n"
324 " - display info for current chip\n"
325 "tca642x output pin 0|1\n"
326 " - set pin as output and drive low or high\n"
327 "tca642x invert pin 0|1\n"
328 " - disable/enable polarity inversion for reads\n"
329 "tca642x input pin\n"
330 " - set pin as input and read value"
333 #endif /* CONFIG_CMD_TCA642X */