Sun Jan 24 19:38:49 2021 UTC ()
remove part of previous that was committed by mistake


(jmcneill)
diff -r1.4 -r1.5 src/sys/dev/i2c/pcai2cmux.c

cvs diff -r1.4 -r1.5 src/sys/dev/i2c/pcai2cmux.c (switch to unified diff)

--- src/sys/dev/i2c/pcai2cmux.c 2021/01/24 19:37:45 1.4
+++ src/sys/dev/i2c/pcai2cmux.c 2021/01/24 19:38:49 1.5
@@ -1,358 +1,354 @@ @@ -1,358 +1,354 @@
1/* $NetBSD: pcai2cmux.c,v 1.4 2021/01/24 19:37:45 jmcneill Exp $ */ 1/* $NetBSD: pcai2cmux.c,v 1.5 2021/01/24 19:38:49 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe. 8 * by Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: pcai2cmux.c,v 1.4 2021/01/24 19:37:45 jmcneill Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: pcai2cmux.c,v 1.5 2021/01/24 19:38:49 jmcneill Exp $");
34 34
35/* 35/*
36 * Driver for NXP PCA954x / PCA984x I2C switches and multiplexers. 36 * Driver for NXP PCA954x / PCA984x I2C switches and multiplexers.
37 * 37 *
38 * There are two flavors of this device: 38 * There are two flavors of this device:
39 * 39 *
40 * - Multiplexers, which connect the upstream bus to one downstream bus 40 * - Multiplexers, which connect the upstream bus to one downstream bus
41 * at a time. 41 * at a time.
42 * 42 *
43 * - Switches, which can connect the upstream bus to one or more downstream 43 * - Switches, which can connect the upstream bus to one or more downstream
44 * busses at a time (which is useful when using an all-call address for 44 * busses at a time (which is useful when using an all-call address for
45 * a large array of PCA9685 LED controllers, for example). 45 * a large array of PCA9685 LED controllers, for example).
46 * 46 *
47 * Alas, the device tree bindings don't have anything specifically for 47 * Alas, the device tree bindings don't have anything specifically for
48 * switches, so we treat the switch variants as basic multiplexers, 48 * switches, so we treat the switch variants as basic multiplexers,
49 * only enabling one downstream bus at a time. 49 * only enabling one downstream bus at a time.
50 * 50 *
51 * Note that some versions of these chips also have interrupt mux 51 * Note that some versions of these chips also have interrupt mux
52 * capability. XXX We do not support this yet. 52 * capability. XXX We do not support this yet.
53 */ 53 */
54 54
55#include <sys/param.h> 55#include <sys/param.h>
56#include <sys/systm.h> 56#include <sys/systm.h>
57#include <sys/device.h> 57#include <sys/device.h>
58 58
59#include <dev/fdt/fdtvar.h> 59#include <dev/fdt/fdtvar.h>
60#include <dev/i2c/i2cmuxvar.h> 60#include <dev/i2c/i2cmuxvar.h>
61 61
62/* There are a maximum of 8 busses supported. */ 62/* There are a maximum of 8 busses supported. */
63#define PCAIICMUX_MAX_BUSSES 8 63#define PCAIICMUX_MAX_BUSSES 8
64 64
65struct pcaiicmux_type { 65struct pcaiicmux_type {
66 unsigned int nchannels; /* # of downstream channels */ 66 unsigned int nchannels; /* # of downstream channels */
67 uint8_t enable_bit; /* if 0, chip is switch type */ 67 uint8_t enable_bit; /* if 0, chip is switch type */
68}; 68};
69 69
70static const struct pcaiicmux_type mux2_type = { 70static const struct pcaiicmux_type mux2_type = {
71 .nchannels = 2, 71 .nchannels = 2,
72 .enable_bit = __BIT(2), 72 .enable_bit = __BIT(2),
73}; 73};
74 74
75static const struct pcaiicmux_type switch2_type = { 75static const struct pcaiicmux_type switch2_type = {
76 .nchannels = 2, 76 .nchannels = 2,
77 .enable_bit = 0, 77 .enable_bit = 0,
78}; 78};
79 79
80static const struct pcaiicmux_type mux4_type = { 80static const struct pcaiicmux_type mux4_type = {
81 .nchannels = 4, 81 .nchannels = 4,
82 .enable_bit = __BIT(2), 82 .enable_bit = __BIT(2),
83}; 83};
84 84
85static const struct pcaiicmux_type switch4_type = { 85static const struct pcaiicmux_type switch4_type = {
86 .nchannels = 4, 86 .nchannels = 4,
87 .enable_bit = 0, 87 .enable_bit = 0,
88}; 88};
89 89
90static const struct pcaiicmux_type mux8_type = { 90static const struct pcaiicmux_type mux8_type = {
91 .nchannels = 8, 91 .nchannels = 8,
92 .enable_bit = __BIT(3), 92 .enable_bit = __BIT(3),
93}; 93};
94 94
95static const struct pcaiicmux_type switch8_type = { 95static const struct pcaiicmux_type switch8_type = {
96 .nchannels = 8, 96 .nchannels = 8,
97 .enable_bit = 0, 97 .enable_bit = 0,
98}; 98};
99 99
100static const struct device_compatible_entry compat_data[] = { 100static const struct device_compatible_entry compat_data[] = {
101 /* PCA9540 - 2 channel i2c mux */ 101 /* PCA9540 - 2 channel i2c mux */
102 { .compat = "nxp,pca9540", 102 { .compat = "nxp,pca9540",
103 .data = &mux2_type }, 103 .data = &mux2_type },
104 104
105 /* PCA9542 - 2 channel i2c mux with interrupts */ 105 /* PCA9542 - 2 channel i2c mux with interrupts */
106 { .compat = "nxp,pca9542", 106 { .compat = "nxp,pca9542",
107 .data = &mux2_type }, 107 .data = &mux2_type },
108 108
109 /* PCA9543 - 2 channel i2c switch with interrupts */ 109 /* PCA9543 - 2 channel i2c switch with interrupts */
110 { .compat = "nxp,pca9543", 110 { .compat = "nxp,pca9543",
111 .data = &switch2_type }, 111 .data = &switch2_type },
112 112
113 /* PCA9544 - 4 channel i2c mux with interrupts */ 113 /* PCA9544 - 4 channel i2c mux with interrupts */
114 { .compat = "nxp,pca9544", 114 { .compat = "nxp,pca9544",
115 .data = &mux4_type }, 115 .data = &mux4_type },
116 116
117 /* PCA9545 - 4 channel i2c switch with interrupts */ 117 /* PCA9545 - 4 channel i2c switch with interrupts */
118 { .compat = "nxp,pca9545", 118 { .compat = "nxp,pca9545",
119 .data = &switch4_type }, 119 .data = &switch4_type },
120 120
121 /* PCA9546 - 4 channel i2c switch */ 121 /* PCA9546 - 4 channel i2c switch */
122 { .compat = "nxp,pca9546", 122 { .compat = "nxp,pca9546",
123 .data = &switch4_type }, 123 .data = &switch4_type },
124 124
125 /* PCA9547 - 8 channel i2c mux */ 125 /* PCA9547 - 8 channel i2c mux */
126 { .compat = "nxp,pca9547", 126 { .compat = "nxp,pca9547",
127 .data = &mux8_type }, 127 .data = &mux8_type },
128 128
129 /* PCA9547 - 8 channel i2c mux (NXP Layerscape ACPI) */ 
130 { .compat = "NXP0002", 
131 .data = &mux8_type }, 
132 
133 /* PCA9548 - 8 channel i2c switch */ 129 /* PCA9548 - 8 channel i2c switch */
134 { .compat = "nxp,pca9548", 130 { .compat = "nxp,pca9548",
135 .data = &switch8_type }, 131 .data = &switch8_type },
136 132
137 /* PCA9846 - 4 channel i2c switch */ 133 /* PCA9846 - 4 channel i2c switch */
138 { .compat = "nxp,pca9846", 134 { .compat = "nxp,pca9846",
139 .data = &switch4_type }, 135 .data = &switch4_type },
140 136
141 /* PCA9847 - 8 channel i2c mux */ 137 /* PCA9847 - 8 channel i2c mux */
142 { .compat = "nxp,pca9847", 138 { .compat = "nxp,pca9847",
143 .data = &mux8_type }, 139 .data = &mux8_type },
144 140
145 /* PCA9848 - 8 channel i2c switch */ 141 /* PCA9848 - 8 channel i2c switch */
146 { .compat = "nxp,pca9848", 142 { .compat = "nxp,pca9848",
147 .data = &switch8_type }, 143 .data = &switch8_type },
148 144
149 /* PCA9849 - 4 channel i2c mux */ 145 /* PCA9849 - 4 channel i2c mux */
150 { .compat = "nxp,pca9849", 146 { .compat = "nxp,pca9849",
151 .data = &mux4_type }, 147 .data = &mux4_type },
152 148
153 { 0 } 149 { 0 }
154}; 150};
155 151
156struct pcaiicmux_softc { 152struct pcaiicmux_softc {
157 struct iicmux_softc sc_iicmux; 153 struct iicmux_softc sc_iicmux;
158 154
159 i2c_addr_t sc_addr; 155 i2c_addr_t sc_addr;
160 int sc_cur_value; 156 int sc_cur_value;
161 157
162 const struct pcaiicmux_type *sc_type; 158 const struct pcaiicmux_type *sc_type;
163 struct fdtbus_gpio_pin *sc_reset_gpio; 159 struct fdtbus_gpio_pin *sc_reset_gpio;
164 160
165 bool sc_idle_disconnect; 161 bool sc_idle_disconnect;
166 162
167 struct pcaiicmux_bus_info { 163 struct pcaiicmux_bus_info {
168 uint8_t enable_value; 164 uint8_t enable_value;
169 } sc_bus_info[PCAIICMUX_MAX_BUSSES]; 165 } sc_bus_info[PCAIICMUX_MAX_BUSSES];
170}; 166};
171 167
172static int 168static int
173pcaiicmux_write(struct pcaiicmux_softc * const sc, uint8_t const val, 169pcaiicmux_write(struct pcaiicmux_softc * const sc, uint8_t const val,
174 int const flags) 170 int const flags)
175{ 171{
176 if ((int)val == sc->sc_cur_value) { 172 if ((int)val == sc->sc_cur_value) {
177 return 0; 173 return 0;
178 } 174 }
179 sc->sc_cur_value = (int)val; 175 sc->sc_cur_value = (int)val;
180 176
181 int const error = 177 int const error =
182 iic_smbus_send_byte(sc->sc_iicmux.sc_i2c_parent, sc->sc_addr, val, 178 iic_smbus_send_byte(sc->sc_iicmux.sc_i2c_parent, sc->sc_addr, val,
183 flags & ~I2C_F_SPEED); 179 flags & ~I2C_F_SPEED);
184 if (error) { 180 if (error) {
185 sc->sc_cur_value = -1; 181 sc->sc_cur_value = -1;
186 } 182 }
187 183
188 return error; 184 return error;
189} 185}
190 186
191/*****************************************************************************/ 187/*****************************************************************************/
192 188
193static void * 189static void *
194pcaiicmux_get_mux_info(struct iicmux_softc * const iicmux) 190pcaiicmux_get_mux_info(struct iicmux_softc * const iicmux)
195{ 191{
196 return container_of(iicmux, struct pcaiicmux_softc, sc_iicmux); 192 return container_of(iicmux, struct pcaiicmux_softc, sc_iicmux);
197} 193}
198 194
199static void * 195static void *
200pcaiicmux_get_bus_info(struct iicmux_bus * const bus) 196pcaiicmux_get_bus_info(struct iicmux_bus * const bus)
201{ 197{
202 struct iicmux_softc * const iicmux = bus->mux; 198 struct iicmux_softc * const iicmux = bus->mux;
203 struct pcaiicmux_softc * const sc = iicmux->sc_mux_data; 199 struct pcaiicmux_softc * const sc = iicmux->sc_mux_data;
204 bus_addr_t addr; 200 bus_addr_t addr;
205 int error; 201 int error;
206 202
207 if (bus->busidx >= sc->sc_type->nchannels) { 203 if (bus->busidx >= sc->sc_type->nchannels) {
208 aprint_error_dev(iicmux->sc_dev, 204 aprint_error_dev(iicmux->sc_dev,
209 "device tree error: bus index %d out of range\n", 205 "device tree error: bus index %d out of range\n",
210 bus->busidx); 206 bus->busidx);
211 return NULL; 207 return NULL;
212 } 208 }
213 209
214 struct pcaiicmux_bus_info * const bus_info = 210 struct pcaiicmux_bus_info * const bus_info =
215 &sc->sc_bus_info[bus->busidx]; 211 &sc->sc_bus_info[bus->busidx];
216 212
217 error = fdtbus_get_reg(bus->phandle, 0, &addr, NULL); 213 error = fdtbus_get_reg(bus->phandle, 0, &addr, NULL);
218 if (error) { 214 if (error) {
219 aprint_error_dev(iicmux->sc_dev, 215 aprint_error_dev(iicmux->sc_dev,
220 "unable to get reg property for bus %d\n", bus->busidx); 216 "unable to get reg property for bus %d\n", bus->busidx);
221 return NULL; 217 return NULL;
222 } 218 }
223 219
224 if (addr >= sc->sc_type->nchannels) { 220 if (addr >= sc->sc_type->nchannels) {
225 aprint_error_dev(iicmux->sc_dev, 221 aprint_error_dev(iicmux->sc_dev,
226 "device tree error: reg property %llu out of range\n", 222 "device tree error: reg property %llu out of range\n",
227 (unsigned long long)addr); 223 (unsigned long long)addr);
228 return NULL; 224 return NULL;
229 } 225 }
230 226
231 /* 227 /*
232 * If it's a mux type, the enable value is the channel number 228 * If it's a mux type, the enable value is the channel number
233 * (from the reg property) OR'd with the enable bit. 229 * (from the reg property) OR'd with the enable bit.
234 * 230 *
235 * If it's a switch type, the enable value is 1 << channel number 231 * If it's a switch type, the enable value is 1 << channel number
236 * (from the reg property). 232 * (from the reg property).
237 */ 233 */
238 if (sc->sc_type->enable_bit) { 234 if (sc->sc_type->enable_bit) {
239 bus_info->enable_value = 235 bus_info->enable_value =
240 (uint8_t)addr | sc->sc_type->enable_bit; 236 (uint8_t)addr | sc->sc_type->enable_bit;
241 } else { 237 } else {
242 bus_info->enable_value = 1 << addr; 238 bus_info->enable_value = 1 << addr;
243 } 239 }
244 240
245 return bus_info; 241 return bus_info;
246} 242}
247 243
248static int 244static int
249pcaiicmux_acquire_bus(struct iicmux_bus * const bus, int const flags) 245pcaiicmux_acquire_bus(struct iicmux_bus * const bus, int const flags)
250{ 246{
251 struct pcaiicmux_softc * const sc = bus->mux->sc_mux_data; 247 struct pcaiicmux_softc * const sc = bus->mux->sc_mux_data;
252 struct pcaiicmux_bus_info * const bus_info = bus->bus_data; 248 struct pcaiicmux_bus_info * const bus_info = bus->bus_data;
253 249
254 return pcaiicmux_write(sc, bus_info->enable_value, flags); 250 return pcaiicmux_write(sc, bus_info->enable_value, flags);
255} 251}
256 252
257static void 253static void
258pcaiicmux_release_bus(struct iicmux_bus * const bus, int const flags) 254pcaiicmux_release_bus(struct iicmux_bus * const bus, int const flags)
259{ 255{
260 struct pcaiicmux_softc * const sc = bus->mux->sc_mux_data; 256 struct pcaiicmux_softc * const sc = bus->mux->sc_mux_data;
261 257
262 if (sc->sc_idle_disconnect) { 258 if (sc->sc_idle_disconnect) {
263 (void) pcaiicmux_write(sc, 0, flags); 259 (void) pcaiicmux_write(sc, 0, flags);
264 } 260 }
265} 261}
266 262
267static const struct iicmux_config pcaiicmux_config = { 263static const struct iicmux_config pcaiicmux_config = {
268 .desc = "PCA954x", 264 .desc = "PCA954x",
269 .get_mux_info = pcaiicmux_get_mux_info, 265 .get_mux_info = pcaiicmux_get_mux_info,
270 .get_bus_info = pcaiicmux_get_bus_info, 266 .get_bus_info = pcaiicmux_get_bus_info,
271 .acquire_bus = pcaiicmux_acquire_bus, 267 .acquire_bus = pcaiicmux_acquire_bus,
272 .release_bus = pcaiicmux_release_bus, 268 .release_bus = pcaiicmux_release_bus,
273}; 269};
274 270
275/*****************************************************************************/ 271/*****************************************************************************/
276 272
277static const struct pcaiicmux_type * 273static const struct pcaiicmux_type *
278pcaiicmux_type_by_compat(const struct i2c_attach_args * const ia) 274pcaiicmux_type_by_compat(const struct i2c_attach_args * const ia)
279{ 275{
280 const struct pcaiicmux_type *type = NULL; 276 const struct pcaiicmux_type *type = NULL;
281 const struct device_compatible_entry *dce; 277 const struct device_compatible_entry *dce;
282 278
283 if ((dce = iic_compatible_lookup(ia, compat_data)) != NULL) 279 if ((dce = iic_compatible_lookup(ia, compat_data)) != NULL)
284 type = dce->data; 280 type = dce->data;
285 281
286 return type; 282 return type;
287} 283}
288 284
289static int 285static int
290pcaiicmux_match(device_t parent, cfdata_t cf, void *aux) 286pcaiicmux_match(device_t parent, cfdata_t cf, void *aux)
291{ 287{
292 struct i2c_attach_args * const ia = aux; 288 struct i2c_attach_args * const ia = aux;
293 int match_result; 289 int match_result;
294 290
295 if (iic_use_direct_match(ia, cf, compat_data, &match_result)) { 291 if (iic_use_direct_match(ia, cf, compat_data, &match_result)) {
296 return match_result; 292 return match_result;
297 } 293 }
298 294
299 /* This device is direct-config only. */ 295 /* This device is direct-config only. */
300 296
301 return 0; 297 return 0;
302} 298}
303 299
304static void 300static void
305pcaiicmux_attach(device_t parent, device_t self, void *aux) 301pcaiicmux_attach(device_t parent, device_t self, void *aux)
306{ 302{
307 struct pcaiicmux_softc * const sc = device_private(self); 303 struct pcaiicmux_softc * const sc = device_private(self);
308 struct i2c_attach_args * const ia = aux; 304 struct i2c_attach_args * const ia = aux;
309 const int phandle = (int)ia->ia_cookie; 305 const int phandle = (int)ia->ia_cookie;
310 int error; 306 int error;
311 307
312 sc->sc_iicmux.sc_dev = self; 308 sc->sc_iicmux.sc_dev = self;
313 sc->sc_iicmux.sc_phandle = phandle; 309 sc->sc_iicmux.sc_phandle = phandle;
314 sc->sc_iicmux.sc_config = &pcaiicmux_config; 310 sc->sc_iicmux.sc_config = &pcaiicmux_config;
315 sc->sc_iicmux.sc_i2c_parent = ia->ia_tag; 311 sc->sc_iicmux.sc_i2c_parent = ia->ia_tag;
316 sc->sc_addr = ia->ia_addr; 312 sc->sc_addr = ia->ia_addr;
317 313
318 sc->sc_type = pcaiicmux_type_by_compat(ia); 314 sc->sc_type = pcaiicmux_type_by_compat(ia);
319 KASSERT(sc->sc_type != NULL); 315 KASSERT(sc->sc_type != NULL);
320 316
321 aprint_naive("\n"); 317 aprint_naive("\n");
322 aprint_normal(": PCA954x I2C %s\n", 318 aprint_normal(": PCA954x I2C %s\n",
323 sc->sc_type->enable_bit ? "mux" : "switch"); 319 sc->sc_type->enable_bit ? "mux" : "switch");
324 320
325 if (of_hasprop(phandle, "i2c-mux-idle-disconnect")) { 321 if (of_hasprop(phandle, "i2c-mux-idle-disconnect")) {
326 sc->sc_idle_disconnect = true; 322 sc->sc_idle_disconnect = true;
327 } 323 }
328 324
329 /* Reset the mux if a reset GPIO is specified. */ 325 /* Reset the mux if a reset GPIO is specified. */
330 sc->sc_reset_gpio = 326 sc->sc_reset_gpio =
331 fdtbus_gpio_acquire(phandle, "reset-gpios", GPIO_PIN_OUTPUT); 327 fdtbus_gpio_acquire(phandle, "reset-gpios", GPIO_PIN_OUTPUT);
332 if (sc->sc_reset_gpio) { 328 if (sc->sc_reset_gpio) {
333 fdtbus_gpio_write(sc->sc_reset_gpio, 1); 329 fdtbus_gpio_write(sc->sc_reset_gpio, 1);
334 delay(10); 330 delay(10);
335 fdtbus_gpio_write(sc->sc_reset_gpio, 0); 331 fdtbus_gpio_write(sc->sc_reset_gpio, 0);
336 delay(10); 332 delay(10);
337 } 333 }
338 334
339 /* Force the mux into a disconnected state. */ 335 /* Force the mux into a disconnected state. */
340 sc->sc_cur_value = -1; 336 sc->sc_cur_value = -1;
341 error = iic_acquire_bus(ia->ia_tag, 0); 337 error = iic_acquire_bus(ia->ia_tag, 0);
342 if (error) { 338 if (error) {
343 aprint_error_dev(self, "failed to acquire I2C bus\n"); 339 aprint_error_dev(self, "failed to acquire I2C bus\n");
344 return; 340 return;
345 } 341 }
346 error = pcaiicmux_write(sc, 0, 0); 342 error = pcaiicmux_write(sc, 0, 0);
347 iic_release_bus(ia->ia_tag, 0); 343 iic_release_bus(ia->ia_tag, 0);
348 if (error) { 344 if (error) {
349 aprint_error_dev(self, 345 aprint_error_dev(self,
350 "failed to set mux to disconnected state\n"); 346 "failed to set mux to disconnected state\n");
351 return; 347 return;
352 } 348 }
353 349
354 iicmux_attach(&sc->sc_iicmux); 350 iicmux_attach(&sc->sc_iicmux);
355} 351}
356 352
357CFATTACH_DECL_NEW(pcaiicmux, sizeof(struct pcaiicmux_softc), 353CFATTACH_DECL_NEW(pcaiicmux, sizeof(struct pcaiicmux_softc),
358 pcaiicmux_match, pcaiicmux_attach, NULL, NULL); 354 pcaiicmux_match, pcaiicmux_attach, NULL, NULL);