This source file includes following definitions.
- pcagpio_match
- pcagpio_attach
- pcagpio_refresh
- pcagpio_gpio_pin_read
- pcagpio_gpio_pin_write
- pcagpio_gpio_pin_ctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/gpio.h>
23 #include <sys/sensors.h>
24
25 #include <dev/i2c/i2cvar.h>
26
27 #include <dev/gpio/gpiovar.h>
28
29
30 #define PCA9554_IN 0x00
31 #define PCA9554_OUT 0x01
32 #define PCA9554_POLARITY 0x02
33 #define PCA9554_CONFIG 0x03
34
35
36 #define PCAGPIO_NPINS 8
37
38 struct pcagpio_softc {
39 struct device sc_dev;
40 i2c_tag_t sc_tag;
41 i2c_addr_t sc_addr;
42 u_int8_t sc_control;
43 u_int8_t sc_polarity;
44
45 struct gpio_chipset_tag sc_gpio_gc;
46 gpio_pin_t sc_gpio_pins[PCAGPIO_NPINS];
47
48 struct ksensor sc_sensor[PCAGPIO_NPINS];
49 struct ksensordev sc_sensordev;
50 };
51
52 int pcagpio_match(struct device *, void *, void *);
53 void pcagpio_attach(struct device *, struct device *, void *);
54 int pcagpio_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *);
55 void pcagpio_refresh(void *);
56
57 int pcagpio_gpio_pin_read(void *, int);
58 void pcagpio_gpio_pin_write(void *, int, int);
59 void pcagpio_gpio_pin_ctl(void *, int, int);
60
61 struct cfattach pcagpio_ca = {
62 sizeof(struct pcagpio_softc), pcagpio_match, pcagpio_attach
63 };
64
65 struct cfdriver pcagpio_cd = {
66 NULL, "pcagpio", DV_DULL
67 };
68
69 int
70 pcagpio_match(struct device *parent, void *match, void *aux)
71 {
72 struct i2c_attach_args *ia = aux;
73
74 if (strcmp(ia->ia_name, "PCA9554") == 0 ||
75 strcmp(ia->ia_name, "PCA9554M") == 0 ||
76 strcmp(ia->ia_name, "pca9555") == 0 ||
77 strcmp(ia->ia_name, "pca9556") == 0 ||
78 strcmp(ia->ia_name, "pca9557") == 0)
79 return (1);
80 return (0);
81 }
82
83 void
84 pcagpio_attach(struct device *parent, struct device *self, void *aux)
85 {
86 struct pcagpio_softc *sc = (struct pcagpio_softc *)self;
87 struct i2c_attach_args *ia = aux;
88 struct gpiobus_attach_args gba;
89 u_int8_t cmd, data;
90 int outputs = 0, i;
91
92 sc->sc_tag = ia->ia_tag;
93 sc->sc_addr = ia->ia_addr;
94
95 cmd = PCA9554_CONFIG;
96 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
97 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
98 printf(": failed to initialize\n");
99 return;
100 }
101 sc->sc_control = data;
102 cmd = PCA9554_POLARITY;
103 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
104 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
105 printf(": failed to initialize\n");
106 return;
107 }
108 sc->sc_polarity = data;
109 cmd = PCA9554_OUT;
110 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
111 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
112 printf(": failed to initialize\n");
113 return;
114 }
115
116
117 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
118 sizeof(sc->sc_sensordev.xname));
119
120 for (i = 0; i < PCAGPIO_NPINS; i++) {
121 sc->sc_sensor[i].type = SENSOR_INDICATOR;
122 if ((sc->sc_control & (1 << i)) == 0) {
123 strlcpy(sc->sc_sensor[i].desc, "out",
124 sizeof(sc->sc_sensor[i].desc));
125 outputs++;
126 } else
127 strlcpy(sc->sc_sensor[i].desc, "in",
128 sizeof(sc->sc_sensor[i].desc));
129
130 }
131
132 if (sensor_task_register(sc, pcagpio_refresh, 5) == NULL) {
133 printf(", unable to register update task\n");
134 return;
135 }
136
137 #if 0
138 for (i = 0; i < PCAGPIO_NPINS; i++)
139 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
140 sensordev_install(&sc->sc_sensordev);
141 #endif
142
143 printf(":");
144 if (PCAGPIO_NPINS - outputs)
145 printf(" %d inputs", PCAGPIO_NPINS - outputs);
146 if (outputs)
147 printf(" %d outputs", outputs);
148 printf("\n");
149
150 for (i = 0; i < PCAGPIO_NPINS; i++) {
151 sc->sc_gpio_pins[i].pin_num = i;
152 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
153
154 if ((sc->sc_control & (1 << i)) == 0) {
155 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_OUTPUT;
156 sc->sc_gpio_pins[i].pin_state =
157 data & (1 << i) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
158 }
159 }
160
161
162 sc->sc_gpio_gc.gp_cookie = sc;
163 sc->sc_gpio_gc.gp_pin_read = pcagpio_gpio_pin_read;
164 sc->sc_gpio_gc.gp_pin_write = pcagpio_gpio_pin_write;
165 sc->sc_gpio_gc.gp_pin_ctl = pcagpio_gpio_pin_ctl;
166
167 gba.gba_name = "gpio";
168 gba.gba_gc = &sc->sc_gpio_gc;
169 gba.gba_pins = sc->sc_gpio_pins;
170 gba.gba_npins = PCAGPIO_NPINS;
171
172 config_found(&sc->sc_dev, &gba, gpiobus_print);
173
174 }
175
176 void
177 pcagpio_refresh(void *arg)
178 {
179 struct pcagpio_softc *sc = arg;
180 u_int8_t cmd, in, out, bit;
181 int i;
182
183 iic_acquire_bus(sc->sc_tag, 0);
184
185 cmd = PCA9554_IN;
186 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
187 sc->sc_addr, &cmd, sizeof cmd, &in, sizeof in, 0))
188 goto invalid;
189
190 cmd = PCA9554_OUT;
191 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
192 sc->sc_addr, &cmd, sizeof cmd, &out, sizeof out, 0))
193 goto invalid;
194
195 for (i = 0; i < PCAGPIO_NPINS; i++) {
196 bit = 1 << i;
197 if ((sc->sc_control & bit))
198 sc->sc_sensor[i].value = (in & bit) ? 1 : 0;
199 else
200 sc->sc_sensor[i].value = (out & bit) ? 1 : 0;
201 }
202
203 invalid:
204 iic_release_bus(sc->sc_tag, 0);
205 }
206
207
208 int
209 pcagpio_gpio_pin_read(void *arg, int pin)
210 {
211 struct pcagpio_softc *sc = arg;
212 u_int8_t cmd, in;
213
214 cmd = PCA9554_IN;
215 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
216 sc->sc_addr, &cmd, sizeof cmd, &in, sizeof in, 0))
217 return 0;
218 return ((in ^ sc->sc_polarity) & (1 << pin)) ? 1 : 0;
219 }
220
221 void
222 pcagpio_gpio_pin_write(void *arg, int pin, int value)
223 {
224 struct pcagpio_softc *sc = arg;
225 u_int8_t cmd, out, mask;
226
227 mask = 0xff ^ (1 << pin);
228 cmd = PCA9554_OUT;
229 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
230 sc->sc_addr, &cmd, sizeof cmd, &out, sizeof out, 0))
231 return;
232 out = (out & mask) | (value << pin);
233
234 cmd = PCA9554_OUT;
235 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
236 sc->sc_addr, &cmd, sizeof cmd, &out, sizeof out, 0))
237 return;
238 }
239
240 void
241 pcagpio_gpio_pin_ctl(void *arg, int pin, int flags)
242 {
243 #if 0
244 struct pcagpio_softc *sc = arg;
245 u_int32_t conf;
246
247 pcagpio_gpio_pin_select(sc, pin);
248 conf = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
249 GSCGPIO_CONF);
250
251 conf &= ~(GSCGPIO_CONF_OUTPUTEN | GSCGPIO_CONF_PUSHPULL |
252 GSCGPIO_CONF_PULLUP);
253 if ((flags & GPIO_PIN_TRISTATE) == 0)
254 conf |= GSCGPIO_CONF_OUTPUTEN;
255 if (flags & GPIO_PIN_PUSHPULL)
256 conf |= GSCGPIO_CONF_PUSHPULL;
257 if (flags & GPIO_PIN_PULLUP)
258 conf |= GSCGPIO_CONF_PULLUP;
259 bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
260 GSCGPIO_CONF, conf);
261 #endif
262 }