1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org>
5 * Copyright (c) 2010 Luiz Otavio O Souza
6 * Copyright (c) 2019 Ian Lepore <ian@freebsd.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 #include "opt_platform.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/gpio.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39
40 #include <dev/gpio/gpiobusvar.h>
41 #include <dev/iicbus/iiconf.h>
42
43 #include "gpiobus_if.h"
44 #include "iicbb_if.h"
45
46 #define GPIOIIC_SCL_DFLT 0
47 #define GPIOIIC_SDA_DFLT 1
48 #define GPIOIIC_MIN_PINS 2
49
50 struct gpioiic_softc
51 {
52 device_t dev;
53 gpio_pin_t sclpin;
54 gpio_pin_t sdapin;
55 };
56
57 #ifdef FDT
58
59 #include <dev/ofw/ofw_bus.h>
60
61 static struct ofw_compat_data compat_data[] = {
62 {"i2c-gpio", true}, /* Standard devicetree compat string */
63 {"gpioiic", true}, /* Deprecated old freebsd compat string */
64 {NULL, false}
65 };
66 OFWBUS_PNP_INFO(compat_data);
67 SIMPLEBUS_PNP_INFO(compat_data);
68
69 static phandle_t
gpioiic_get_node(device_t bus,device_t dev)70 gpioiic_get_node(device_t bus, device_t dev)
71 {
72
73 /* Share our fdt node with iicbus so it can find its child nodes. */
74 return (ofw_bus_get_node(bus));
75 }
76
77 static int
gpioiic_setup_fdt_pins(struct gpioiic_softc * sc)78 gpioiic_setup_fdt_pins(struct gpioiic_softc *sc)
79 {
80 phandle_t node;
81 int err;
82
83 node = ofw_bus_get_node(sc->dev);
84
85 /*
86 * Historically, we used the first two array elements of the gpios
87 * property. The modern bindings specify separate scl-gpios and
88 * sda-gpios properties. We cope with whichever is present.
89 */
90 if (OF_hasprop(node, "gpios")) {
91 if ((err = gpio_pin_get_by_ofw_idx(sc->dev, node,
92 GPIOIIC_SCL_DFLT, &sc->sclpin)) != 0) {
93 device_printf(sc->dev, "invalid gpios property\n");
94 return (err);
95 }
96 if ((err = gpio_pin_get_by_ofw_idx(sc->dev, node,
97 GPIOIIC_SDA_DFLT, &sc->sdapin)) != 0) {
98 device_printf(sc->dev, "ivalid gpios property\n");
99 return (err);
100 }
101 } else {
102 if ((err = gpio_pin_get_by_ofw_property(sc->dev, node,
103 "scl-gpios", &sc->sclpin)) != 0) {
104 device_printf(sc->dev, "missing scl-gpios property\n");
105 return (err);
106 }
107 if ((err = gpio_pin_get_by_ofw_property(sc->dev, node,
108 "sda-gpios", &sc->sdapin)) != 0) {
109 device_printf(sc->dev, "missing sda-gpios property\n");
110 return (err);
111 }
112 }
113 return (0);
114 }
115 #endif /* FDT */
116
117 static int
gpioiic_setup_hinted_pins(struct gpioiic_softc * sc)118 gpioiic_setup_hinted_pins(struct gpioiic_softc *sc)
119 {
120 device_t busdev;
121 const char *busname, *devname;
122 int err, numpins, sclnum, sdanum, unit;
123
124 devname = device_get_name(sc->dev);
125 unit = device_get_unit(sc->dev);
126 busdev = device_get_parent(sc->dev);
127
128 /*
129 * If there is not an "at" hint naming our actual parent, then we
130 * weren't instantiated as a child of gpiobus via hints, and we thus
131 * can't access ivars that only exist for such children.
132 */
133 if (resource_string_value(devname, unit, "at", &busname) != 0 ||
134 (strcmp(busname, device_get_nameunit(busdev)) != 0 &&
135 strcmp(busname, device_get_name(busdev)) != 0)) {
136 return (ENOENT);
137 }
138
139 /* Make sure there were hints for at least two pins. */
140 numpins = gpiobus_get_npins(sc->dev);
141 if (numpins < GPIOIIC_MIN_PINS) {
142 #ifdef FDT
143 /*
144 * Be silent when there are no hints on FDT systems; the FDT
145 * data will provide the pin config (we'll whine if it doesn't).
146 */
147 if (numpins == 0) {
148 return (ENOENT);
149 }
150 #endif
151 device_printf(sc->dev,
152 "invalid pins hint; it must contain at least %d pins\n",
153 GPIOIIC_MIN_PINS);
154 return (EINVAL);
155 }
156
157 /*
158 * Our parent bus has already parsed the pins hint and it will use that
159 * info when we call gpio_pin_get_by_child_index(). But we have to
160 * handle the scl/sda index hints that tell us which of the two pins is
161 * the clock and which is the data. They're optional, but if present
162 * they must be a valid index (0 <= index < numpins).
163 */
164 if ((err = resource_int_value(devname, unit, "scl", &sclnum)) != 0)
165 sclnum = GPIOIIC_SCL_DFLT;
166 else if (sclnum < 0 || sclnum >= numpins) {
167 device_printf(sc->dev, "invalid scl hint %d\n", sclnum);
168 return (EINVAL);
169 }
170 if ((err = resource_int_value(devname, unit, "sda", &sdanum)) != 0)
171 sdanum = GPIOIIC_SDA_DFLT;
172 else if (sdanum < 0 || sdanum >= numpins) {
173 device_printf(sc->dev, "invalid sda hint %d\n", sdanum);
174 return (EINVAL);
175 }
176
177 /* Allocate gpiobus_pin structs for the pins we found above. */
178 if ((err = gpio_pin_get_by_child_index(sc->dev, sclnum,
179 &sc->sclpin)) != 0)
180 return (err);
181 if ((err = gpio_pin_get_by_child_index(sc->dev, sdanum,
182 &sc->sdapin)) != 0)
183 return (err);
184
185 return (0);
186 }
187
188 static void
gpioiic_setsda(device_t dev,int val)189 gpioiic_setsda(device_t dev, int val)
190 {
191 struct gpioiic_softc *sc = device_get_softc(dev);
192
193 if (val) {
194 gpio_pin_setflags(sc->sdapin, GPIO_PIN_INPUT);
195 } else {
196 gpio_pin_setflags(sc->sdapin,
197 GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
198 gpio_pin_set_active(sc->sdapin, 0);
199 }
200 }
201
202 static void
gpioiic_setscl(device_t dev,int val)203 gpioiic_setscl(device_t dev, int val)
204 {
205 struct gpioiic_softc *sc = device_get_softc(dev);
206
207 if (val) {
208 gpio_pin_setflags(sc->sclpin, GPIO_PIN_INPUT);
209 } else {
210 gpio_pin_setflags(sc->sclpin,
211 GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
212 gpio_pin_set_active(sc->sclpin, 0);
213 }
214 }
215
216 static int
gpioiic_getscl(device_t dev)217 gpioiic_getscl(device_t dev)
218 {
219 struct gpioiic_softc *sc = device_get_softc(dev);
220 bool val;
221
222 gpio_pin_setflags(sc->sclpin, GPIO_PIN_INPUT);
223 gpio_pin_is_active(sc->sclpin, &val);
224 return (val);
225 }
226
227 static int
gpioiic_getsda(device_t dev)228 gpioiic_getsda(device_t dev)
229 {
230 struct gpioiic_softc *sc = device_get_softc(dev);
231 bool val;
232
233 gpio_pin_setflags(sc->sdapin, GPIO_PIN_INPUT);
234 gpio_pin_is_active(sc->sdapin, &val);
235 return (val);
236 }
237
238 static int
gpioiic_reset(device_t dev,u_char speed,u_char addr,u_char * oldaddr)239 gpioiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
240 {
241 struct gpioiic_softc *sc = device_get_softc(dev);
242
243 /* Stop driving the bus pins. */
244 gpio_pin_setflags(sc->sdapin, GPIO_PIN_INPUT);
245 gpio_pin_setflags(sc->sclpin, GPIO_PIN_INPUT);
246
247 /* Indicate that we have no slave address (master mode). */
248 return (IIC_ENOADDR);
249 }
250
251 static void
gpioiic_cleanup(struct gpioiic_softc * sc)252 gpioiic_cleanup(struct gpioiic_softc *sc)
253 {
254
255 device_delete_children(sc->dev);
256
257 if (sc->sclpin != NULL)
258 gpio_pin_release(sc->sclpin);
259
260 if (sc->sdapin != NULL)
261 gpio_pin_release(sc->sdapin);
262 }
263
264 static int
gpioiic_probe(device_t dev)265 gpioiic_probe(device_t dev)
266 {
267 int rv;
268
269 /*
270 * By default we only bid to attach if specifically added by our parent
271 * (usually via hint.gpioiic.#.at=busname). On FDT systems we bid as
272 * the default driver based on being configured in the FDT data.
273 */
274 rv = BUS_PROBE_NOWILDCARD;
275
276 #ifdef FDT
277 if (ofw_bus_status_okay(dev) &&
278 ofw_bus_search_compatible(dev, compat_data)->ocd_data)
279 rv = BUS_PROBE_DEFAULT;
280 #endif
281
282 device_set_desc(dev, "GPIO I2C");
283
284 return (rv);
285 }
286
287 static int
gpioiic_attach(device_t dev)288 gpioiic_attach(device_t dev)
289 {
290 struct gpioiic_softc *sc = device_get_softc(dev);
291 int err;
292
293 sc->dev = dev;
294
295 /* Acquire our gpio pins. */
296 err = gpioiic_setup_hinted_pins(sc);
297 #ifdef FDT
298 if (err != 0)
299 err = gpioiic_setup_fdt_pins(sc);
300 #endif
301 if (err != 0) {
302 device_printf(sc->dev, "no pins configured\n");
303 gpioiic_cleanup(sc);
304 return (ENXIO);
305 }
306
307 /*
308 * Say what we came up with for pin config.
309 * NB: in the !FDT case the controller driver might not be set up enough
310 * for GPIO_GET_BUS() to work. Also, our parent is the only gpiobus
311 * that can provide our pins.
312 */
313 device_printf(dev, "SCL pin: %s:%d, SDA pin: %s:%d\n",
314 #ifdef FDT
315 device_get_nameunit(GPIO_GET_BUS(sc->sclpin->dev)), sc->sclpin->pin,
316 device_get_nameunit(GPIO_GET_BUS(sc->sdapin->dev)), sc->sdapin->pin);
317 #else
318 device_get_nameunit(device_get_parent(dev)), sc->sclpin->pin,
319 device_get_nameunit(device_get_parent(dev)), sc->sdapin->pin);
320 #endif
321
322 /* Add the bitbang driver as our only child; it will add iicbus. */
323 device_add_child(sc->dev, "iicbb", DEVICE_UNIT_ANY);
324 bus_attach_children(dev);
325 return (0);
326 }
327
328 static int
gpioiic_detach(device_t dev)329 gpioiic_detach(device_t dev)
330 {
331 struct gpioiic_softc *sc = device_get_softc(dev);
332 int err;
333
334 if ((err = bus_detach_children(dev)) != 0)
335 return (err);
336
337 gpioiic_cleanup(sc);
338
339 return (0);
340 }
341
342 static device_method_t gpioiic_methods[] = {
343 /* Device interface */
344 DEVMETHOD(device_probe, gpioiic_probe),
345 DEVMETHOD(device_attach, gpioiic_attach),
346 DEVMETHOD(device_detach, gpioiic_detach),
347
348 /* iicbb interface */
349 DEVMETHOD(iicbb_setsda, gpioiic_setsda),
350 DEVMETHOD(iicbb_setscl, gpioiic_setscl),
351 DEVMETHOD(iicbb_getsda, gpioiic_getsda),
352 DEVMETHOD(iicbb_getscl, gpioiic_getscl),
353 DEVMETHOD(iicbb_reset, gpioiic_reset),
354
355 #ifdef FDT
356 /* OFW bus interface */
357 DEVMETHOD(ofw_bus_get_node, gpioiic_get_node),
358 #endif
359
360 DEVMETHOD_END
361 };
362
363 static driver_t gpioiic_driver = {
364 "gpioiic",
365 gpioiic_methods,
366 sizeof(struct gpioiic_softc),
367 };
368
369 DRIVER_MODULE(gpioiic, gpiobus, gpioiic_driver, 0, 0);
370 DRIVER_MODULE(gpioiic, simplebus, gpioiic_driver, 0, 0);
371 DRIVER_MODULE(iicbb, gpioiic, iicbb_driver, 0, 0);
372 MODULE_DEPEND(gpioiic, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
373 MODULE_DEPEND(gpioiic, gpiobus, 1, 1, 1);
374