| @@ -1,79 +1,79 @@ | | | @@ -1,79 +1,79 @@ |
1 | /* $NetBSD: i2cmux.c,v 1.1 2020/12/28 20:29:57 thorpej Exp $ */ | | 1 | /* $NetBSD: i2cmux.c,v 1.2 2021/01/24 19:35:21 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: i2cmux.c,v 1.1 2020/12/28 20:29:57 thorpej Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: i2cmux.c,v 1.2 2021/01/24 19:35:21 jmcneill Exp $"); |
34 | | | 34 | |
35 | #include <sys/types.h> | | 35 | #include <sys/types.h> |
36 | #include <sys/device.h> | | 36 | #include <sys/device.h> |
37 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
38 | #include <sys/kmem.h> | | 38 | #include <sys/kmem.h> |
39 | | | 39 | |
40 | #include <dev/fdt/fdtvar.h> | | 40 | #include <dev/fdt/fdtvar.h> |
41 | #include <dev/i2c/i2cvar.h> | | 41 | #include <dev/i2c/i2cvar.h> |
42 | #include <dev/i2c/i2cmuxvar.h> | | 42 | #include <dev/i2c/i2cmuxvar.h> |
43 | | | 43 | |
44 | /* | | 44 | /* |
45 | * i2c mux | | 45 | * i2c mux |
46 | * | | 46 | * |
47 | * This works by interposing a set of virtual controllers behind the real | | 47 | * This works by interposing a set of virtual controllers behind the real |
48 | * i2c controller. We provide our own acquire and release functions that | | 48 | * i2c controller. We provide our own acquire and release functions that |
49 | * perform the following tasks: | | 49 | * perform the following tasks: |
50 | * | | 50 | * |
51 | * acquire -> acquire parent controller, program mux | | 51 | * acquire -> acquire parent controller, program mux |
52 | * | | 52 | * |
53 | * release -> idle mux, release parent controller | | 53 | * release -> idle mux, release parent controller |
54 | * | | 54 | * |
55 | * All of the actual I/O operations are transparently passed through. | | 55 | * All of the actual I/O operations are transparently passed through. |
56 | * | | 56 | * |
57 | * N.B. the locking order; the generic I2C layer has already acquired | | 57 | * N.B. the locking order; the generic I2C layer has already acquired |
58 | * our virtual controller's mutex before calling our acquire function, | | 58 | * our virtual controller's mutex before calling our acquire function, |
59 | * and we will then acquire the real controller's mutex when we acquire | | 59 | * and we will then acquire the real controller's mutex when we acquire |
60 | * the bus, so the order is: | | 60 | * the bus, so the order is: |
61 | * | | 61 | * |
62 | * mux virtual controller -> parent controller | | 62 | * mux virtual controller -> parent controller |
63 | * | | 63 | * |
64 | * These are common routines used by various i2c mux controller | | 64 | * These are common routines used by various i2c mux controller |
65 | * implementations (gpio, pin mux, i2c device, etc.). | | 65 | * implementations (gpio, pin mux, i2c device, etc.). |
66 | */ | | 66 | */ |
67 | | | 67 | |
68 | /*****************************************************************************/ | | 68 | /*****************************************************************************/ |
69 | | | 69 | |
70 | static int | | 70 | static int |
71 | iicmux_acquire_bus(void * const v, int const flags) | | 71 | iicmux_acquire_bus(void * const v, int const flags) |
72 | { | | 72 | { |
73 | struct iicmux_bus * const bus = v; | | 73 | struct iicmux_bus * const bus = v; |
74 | struct iicmux_softc * const sc = bus->mux; | | 74 | struct iicmux_softc * const sc = bus->mux; |
75 | int error; | | 75 | int error; |
76 | | | 76 | |
77 | error = iic_acquire_bus(sc->sc_i2c_parent, flags); | | 77 | error = iic_acquire_bus(sc->sc_i2c_parent, flags); |
78 | if (error) { | | 78 | if (error) { |
79 | return error; | | 79 | return error; |
| @@ -131,38 +131,38 @@ iicmux_count_children(struct iicmux_soft | | | @@ -131,38 +131,38 @@ iicmux_count_children(struct iicmux_soft |
131 | */ | | 131 | */ |
132 | sc->sc_i2c_mux_phandle = child; | | 132 | sc->sc_i2c_mux_phandle = child; |
133 | goto restart; | | 133 | goto restart; |
134 | } | | 134 | } |
135 | count++; | | 135 | count++; |
136 | } | | 136 | } |
137 | | | 137 | |
138 | return count; | | 138 | return count; |
139 | } | | 139 | } |
140 | | | 140 | |
141 | /* XXX iicbus_print() should be able to do this. */ | | 141 | /* XXX iicbus_print() should be able to do this. */ |
142 | static int | | 142 | static int |
143 | iicmux_print(void * const aux, const char * const pnp) | | 143 | iicmux_print(void * const aux, const char * const pnp) |
144 | { | | 144 | { |
145 | i2c_tag_t const tag = aux; | | 145 | i2c_tag_t const tag = aux; |
146 | struct iicmux_bus * const bus = tag->ic_cookie; | | 146 | struct iicmux_bus * const bus = tag->ic_cookie; |
147 | int rv; | | 147 | int rv; |
148 | | | 148 | |
149 | rv = iicbus_print(aux, pnp); | | 149 | rv = iicbus_print(aux, pnp); |
150 | aprint_normal(" bus %d", bus->busidx); | | 150 | aprint_normal(" bus %d", bus->busidx); |
151 | | | 151 | |
152 | return rv; | | 152 | return rv; |
153 | } | | 153 | } |
154 | | | 154 | |
155 | static void | | 155 | static void |
156 | iicmux_attach_bus(struct iicmux_softc * const sc, | | 156 | iicmux_attach_bus(struct iicmux_softc * const sc, |
157 | int const phandle, int const busidx) | | 157 | int const phandle, int const busidx) |
158 | { | | 158 | { |
159 | struct iicmux_bus * const bus = &sc->sc_busses[busidx]; | | 159 | struct iicmux_bus * const bus = &sc->sc_busses[busidx]; |
160 | | | 160 | |
161 | bus->mux = sc; | | 161 | bus->mux = sc; |
162 | bus->busidx = busidx; | | 162 | bus->busidx = busidx; |
163 | bus->phandle = phandle; | | 163 | bus->phandle = phandle; |
164 | | | 164 | |
165 | bus->bus_data = sc->sc_config->get_bus_info(bus); | | 165 | bus->bus_data = sc->sc_config->get_bus_info(bus); |
166 | if (bus->bus_data == NULL) { | | 166 | if (bus->bus_data == NULL) { |
167 | aprint_error_dev(sc->sc_dev, | | 167 | aprint_error_dev(sc->sc_dev, |
168 | "unable to get info for bus %d\n", busidx); | | 168 | "unable to get info for bus %d\n", busidx); |