2 * PCF8575 I2C GPIO EXPANDER DRIVER
4 * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
6 * Vignesh R <vigneshr@ti.com>
8 * SPDX-License-Identifier: GPL-2.0
11 * Driver for TI PCF-8575 16-bit I2C gpio expander. Based on
12 * gpio-pcf857x Linux Kernel(v4.7) driver.
14 * Copyright (C) 2007 David Brownell
19 * NOTE: The driver and devicetree bindings are borrowed from Linux
20 * Kernel, but driver does not support all PCF857x devices. It currently
21 * supports PCF8575 16-bit expander by TI and NXP.
23 * TODO(vigneshr@ti.com):
24 * Support 8 bit PCF857x compatible expanders.
30 #include <asm-generic/gpio.h>
32 DECLARE_GLOBAL_DATA_PTR
;
35 int gpio_count
; /* No. GPIOs supported by the chip */
37 /* NOTE: these chips have strange "quasi-bidirectional" I/O pins.
38 * We can't actually know whether a pin is configured (a) as output
39 * and driving the signal low, or (b) as input and reporting a low
40 * value ... without knowing the last value written since the chip
41 * came out of reset (if any). We can't read the latched output.
42 * In short, the only reliable solution for setting up pin direction
43 * is to do it explicitly.
45 * Using "out" avoids that trouble. When left initialized to zero,
46 * our software copy of the "latch" then matches the chip's all-ones
47 * reset state. Otherwise it flags pins to be driven low.
49 unsigned int out
; /* software latch */
50 const char *bank_name
; /* Name of the expander bank */
53 /* Read/Write to 16-bit I/O expander */
55 static int pcf8575_i2c_write_le16(struct udevice
*dev
, unsigned int word
)
57 struct dm_i2c_chip
*chip
= dev_get_parent_platdata(dev
);
58 u8 buf
[2] = { word
& 0xff, word
>> 8, };
61 ret
= dm_i2c_write(dev
, 0, buf
, 2);
63 printf("%s i2c write failed to addr %x\n", __func__
,
69 static int pcf8575_i2c_read_le16(struct udevice
*dev
)
71 struct dm_i2c_chip
*chip
= dev_get_parent_platdata(dev
);
75 ret
= dm_i2c_read(dev
, 0, buf
, 2);
77 printf("%s i2c read failed from addr %x\n", __func__
,
82 return (buf
[1] << 8) | buf
[0];
85 static int pcf8575_direction_input(struct udevice
*dev
, unsigned offset
)
87 struct pcf8575_chip
*plat
= dev_get_platdata(dev
);
90 plat
->out
|= BIT(offset
);
91 status
= pcf8575_i2c_write_le16(dev
, plat
->out
);
96 static int pcf8575_direction_output(struct udevice
*dev
,
97 unsigned int offset
, int value
)
99 struct pcf8575_chip
*plat
= dev_get_platdata(dev
);
103 plat
->out
|= BIT(offset
);
105 plat
->out
&= ~BIT(offset
);
107 ret
= pcf8575_i2c_write_le16(dev
, plat
->out
);
112 static int pcf8575_get_value(struct udevice
*dev
, unsigned int offset
)
116 value
= pcf8575_i2c_read_le16(dev
);
118 return (value
< 0) ? value
: ((value
& BIT(offset
)) >> offset
);
121 static int pcf8575_set_value(struct udevice
*dev
, unsigned int offset
,
124 return pcf8575_direction_output(dev
, offset
, value
);
127 static int pcf8575_ofdata_platdata(struct udevice
*dev
)
129 struct pcf8575_chip
*plat
= dev_get_platdata(dev
);
130 struct gpio_dev_priv
*uc_priv
= dev_get_uclass_priv(dev
);
134 uc_priv
->gpio_count
= fdtdec_get_int(gd
->fdt_blob
, dev
->of_offset
,
136 uc_priv
->bank_name
= fdt_getprop(gd
->fdt_blob
, dev
->of_offset
,
137 "gpio-bank-name", NULL
);
138 if (!uc_priv
->bank_name
)
139 uc_priv
->bank_name
= fdt_get_name(gd
->fdt_blob
,
140 dev
->of_offset
, NULL
);
142 n_latch
= fdtdec_get_uint(gd
->fdt_blob
, dev
->of_offset
,
143 "lines-initial-states", 0);
144 plat
->out
= ~n_latch
;
149 static int pcf8575_gpio_probe(struct udevice
*dev
)
151 struct gpio_dev_priv
*uc_priv
= dev_get_uclass_priv(dev
);
153 debug("%s GPIO controller with %d gpios probed\n",
154 uc_priv
->bank_name
, uc_priv
->gpio_count
);
159 static const struct dm_gpio_ops pcf8575_gpio_ops
= {
160 .direction_input
= pcf8575_direction_input
,
161 .direction_output
= pcf8575_direction_output
,
162 .get_value
= pcf8575_get_value
,
163 .set_value
= pcf8575_set_value
,
166 static const struct udevice_id pcf8575_gpio_ids
[] = {
167 { .compatible
= "nxp,pcf8575" },
168 { .compatible
= "ti,pcf8575" },
172 U_BOOT_DRIVER(gpio_pcf8575
) = {
173 .name
= "gpio_pcf8575",
175 .ops
= &pcf8575_gpio_ops
,
176 .of_match
= pcf8575_gpio_ids
,
177 .ofdata_to_platdata
= pcf8575_ofdata_platdata
,
178 .probe
= pcf8575_gpio_probe
,
179 .platdata_auto_alloc_size
= sizeof(struct pcf8575_chip
),