xref: /freebsd/sys/dev/gpio/gpiospi.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1 /*-
2  * Copyright (c) 2011, Aleksandr Rybalko <ray@dlink.ua>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include "opt_gpio.h"
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/rman.h>
40 #include <sys/sysctl.h>
41 
42 #include <sys/gpio.h>
43 #include "gpiobus_if.h"
44 
45 #include <dev/gpio/gpiobusvar.h>
46 
47 #include <dev/spibus/spi.h>
48 #include <dev/spibus/spibusvar.h>
49 #include "spibus_if.h"
50 
51 #ifdef	GPIO_SPI_DEBUG
52 #define	dprintf printf
53 #else
54 #define	dprintf(x, arg...)
55 #endif	/* GPIO_SPI_DEBUG */
56 
57 struct gpio_spi_softc {
58 	device_t	sc_dev;
59 	device_t	sc_busdev;
60 	int		sc_freq;
61 	uint8_t		sc_sclk;
62 	uint8_t		sc_miso;
63 	uint8_t		sc_mosi;
64 	uint8_t		sc_cs0;
65 	uint8_t		sc_cs1;
66 	uint8_t		sc_cs2;
67 	uint8_t		sc_cs3;
68 };
69 
70 static void gpio_spi_chip_activate(struct gpio_spi_softc *, int);
71 static void gpio_spi_chip_deactivate(struct gpio_spi_softc *, int);
72 
73 static int
74 gpio_spi_probe(device_t dev)
75 {
76 	device_set_desc(dev, "GPIO SPI bit-banging driver");
77 	return (0);
78 }
79 
80 static void
81 gpio_delay(struct gpio_spi_softc *sc)
82 {
83 	int d;
84 
85 	d = sc->sc_freq / 1000000;
86 	if (d == 0)
87 		d = 1;
88 
89 	DELAY(d);
90 }
91 
92 static int
93 gpio_spi_attach(device_t dev)
94 {
95 	uint32_t value;
96 	struct gpio_spi_softc *sc;
97 
98 	sc = device_get_softc(dev);
99 	sc->sc_dev = dev;
100 	sc->sc_busdev = device_get_parent(dev);
101 
102 	/* Required variables */
103 	if (resource_int_value(device_get_name(dev),
104 	    device_get_unit(dev), "sclk", &value))
105 		 return (ENXIO);
106 	sc->sc_sclk = value & 0xff;
107 
108 	if (resource_int_value(device_get_name(dev),
109 	    device_get_unit(dev), "mosi", &value))
110 		 return (ENXIO);
111 	sc->sc_mosi = value & 0xff;
112 
113 	/* Handle no miso; we just never read back from the device */
114 	if (resource_int_value(device_get_name(dev),
115 	    device_get_unit(dev), "miso", &value))
116 		 value = 0xff;
117 	sc->sc_miso = value & 0xff;
118 
119 	if (resource_int_value(device_get_name(dev),
120 	    device_get_unit(dev), "cs0", &value))
121 		 return (ENXIO);
122 	sc->sc_cs0 = value & 0xff;
123 
124 	/* Optional variables */
125 	if (resource_int_value(device_get_name(dev),
126 	    device_get_unit(dev), "cs1", &value))
127 		value = 0xff;
128 	sc->sc_cs1 = value & 0xff;
129 
130 	if (resource_int_value(device_get_name(dev),
131 	    device_get_unit(dev), "cs2", &value))
132 		value = 0xff;
133 	sc->sc_cs2 = value & 0xff;
134 
135 	if (resource_int_value(device_get_name(dev),
136 	    device_get_unit(dev), "cs3", &value))
137 		value = 0xff;
138 	sc->sc_cs3 = value & 0xff;
139 
140 	/* Default to 100KHz */
141 	if (resource_int_value(device_get_name(dev),
142 	    device_get_unit(dev), "freq", &value)) {
143 		value = 100000;
144 	}
145 	sc->sc_freq = value;
146 
147 	if (bootverbose) {
148 		device_printf(dev, "frequency: %d Hz\n",
149 		    sc->sc_freq);
150 		device_printf(dev,
151 		    "Use GPIO pins: sclk=%d, mosi=%d, miso=%d, "
152 		    "cs0=%d, cs1=%d, cs2=%d, cs3=%d\n",
153 		    sc->sc_sclk, sc->sc_mosi, sc->sc_miso,
154 		    sc->sc_cs0, sc->sc_cs1, sc->sc_cs2, sc->sc_cs3);
155 	}
156 
157 	/* Set directions */
158 	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_sclk,
159 	    GPIO_PIN_OUTPUT|GPIO_PIN_PULLDOWN);
160 	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_mosi,
161 	    GPIO_PIN_OUTPUT|GPIO_PIN_PULLDOWN);
162 	if (sc->sc_miso != 0xff) {
163 		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_miso,
164 		    GPIO_PIN_INPUT|GPIO_PIN_PULLDOWN);
165 	}
166 
167 	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_cs0,
168 	    GPIO_PIN_OUTPUT|GPIO_PIN_PULLUP);
169 
170 	if (sc->sc_cs1 != 0xff)
171 		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_cs1,
172 		    GPIO_PIN_OUTPUT|GPIO_PIN_PULLUP);
173 	if (sc->sc_cs2 != 0xff)
174 		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_cs2,
175 		    GPIO_PIN_OUTPUT|GPIO_PIN_PULLUP);
176 	if (sc->sc_cs3 != 0xff)
177 		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sc_cs3,
178 		    GPIO_PIN_OUTPUT|GPIO_PIN_PULLUP);
179 
180 	gpio_spi_chip_deactivate(sc, -1);
181 
182 	device_add_child(dev, "spibus", -1);
183 	return (bus_generic_attach(dev));
184 }
185 
186 static int
187 gpio_spi_detach(device_t dev)
188 {
189 
190 	return (0);
191 }
192 
193 static void
194 gpio_spi_chip_activate(struct gpio_spi_softc *sc, int cs)
195 {
196 
197 	/* called with locked gpiobus */
198 	switch (cs) {
199 	case 0:
200 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
201 		    sc->sc_cs0, 0);
202 		break;
203 	case 1:
204 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
205 		    sc->sc_cs1, 0);
206 		break;
207 	case 2:
208 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
209 		    sc->sc_cs2, 0);
210 		break;
211 	case 3:
212 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
213 		    sc->sc_cs3, 0);
214 		break;
215 	default:
216 		device_printf(sc->sc_dev, "don't have CS%d\n", cs);
217 	}
218 
219 	gpio_delay(sc);
220 }
221 
222 static void
223 gpio_spi_chip_deactivate(struct gpio_spi_softc *sc, int cs)
224 {
225 
226 	/* called wth locked gpiobus */
227 	/*
228 	 * Put CSx to high
229 	 */
230 	switch (cs) {
231 	case -1:
232 		/* All CS */
233 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
234 		    sc->sc_cs0, 1);
235 		if (sc->sc_cs1 == 0xff) break;
236 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
237 		    sc->sc_cs1, 1);
238 		if (sc->sc_cs2 == 0xff) break;
239 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
240 		    sc->sc_cs2, 1);
241 		if (sc->sc_cs3 == 0xff) break;
242 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
243 		    sc->sc_cs3, 1);
244 		break;
245 	case 0:
246 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
247 		    sc->sc_cs0, 1);
248 		break;
249 	case 1:
250 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
251 		    sc->sc_cs1, 1);
252 		break;
253 	case 2:
254 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
255 		    sc->sc_cs2, 1);
256 		break;
257 	case 3:
258 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
259 		    sc->sc_cs3, 1);
260 		break;
261 	default:
262 		device_printf(sc->sc_dev, "don't have CS%d\n", cs);
263 	}
264 }
265 
266 static uint8_t
267 gpio_spi_txrx(struct gpio_spi_softc *sc, int cs, int mode, uint8_t data)
268 {
269 	uint32_t mask, out = 0;
270 	unsigned int bit;
271 
272 
273 	/* called with locked gpiobus */
274 
275 	for (mask = 0x80; mask > 0; mask >>= 1) {
276 		if ((mode == SPIBUS_MODE_CPOL) ||
277 		    (mode == SPIBUS_MODE_CPHA)) {
278 			/* If mode 1 or 2 */
279 
280 			/* first step */
281 			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
282 			    sc->sc_mosi, (data & mask)?1:0);
283 			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
284 			    sc->sc_sclk, 0);
285 			gpio_delay(sc);
286 			/* second step */
287 			if (sc->sc_miso != 0xff) {
288 				GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev,
289 				    sc->sc_miso, &bit);
290 				out |= bit?mask:0;
291 			}
292 			/* Data captured */
293 			gpio_delay(sc);
294 			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
295 			    sc->sc_sclk, 1);
296 			gpio_delay(sc);
297 		} else {
298 			/* If mode 0 or 3 */
299 
300 			/* first step */
301 			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
302 			    sc->sc_mosi, (data & mask)?1:0);
303 			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
304 			    sc->sc_sclk, 1);
305 			gpio_delay(sc);
306 			/* second step */
307 			if (sc->sc_miso != 0xff) {
308 				GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev,
309 				    sc->sc_miso, &bit);
310 				out |= bit?mask:0;
311 			}
312 			 /* Data captured */
313 			gpio_delay(sc);
314 			GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
315 			    sc->sc_sclk, 0);
316 			gpio_delay(sc);
317 		}
318 	}
319 
320 	return (out & 0xff);
321 }
322 
323 static int
324 gpio_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
325 {
326 	struct gpio_spi_softc *sc;
327 	uint8_t *buf_in, *buf_out;
328 	struct spibus_ivar *devi = SPIBUS_IVAR(child);
329 	int i;
330 
331 	sc = device_get_softc(dev);
332 
333 	KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
334 	    ("TX/RX command sizes should be equal"));
335 	KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
336 	    ("TX/RX data sizes should be equal"));
337 
338 	gpio_spi_chip_activate(sc, devi->cs);
339 
340 	/* Preset pins */
341 	if ((devi->mode == SPIBUS_MODE_CPOL) ||
342 	    (devi->mode == SPIBUS_MODE_CPHA)) {
343 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
344 		    sc->sc_sclk, 1);
345 	} else {
346 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
347 		    sc->sc_sclk, 0);
348 	}
349 
350 	/*
351 	 * Transfer command
352 	 */
353 	buf_out = (uint8_t *)cmd->tx_cmd;
354 	buf_in = (uint8_t *)cmd->rx_cmd;
355 
356 	for (i = 0; i < cmd->tx_cmd_sz; i++)
357 		buf_in[i] = gpio_spi_txrx(sc, devi->cs, devi->mode, buf_out[i]);
358 
359 	/*
360 	 * Receive/transmit data (depends on command)
361 	 */
362 	buf_out = (uint8_t *)cmd->tx_data;
363 	buf_in = (uint8_t *)cmd->rx_data;
364 	for (i = 0; i < cmd->tx_data_sz; i++)
365 		buf_in[i] = gpio_spi_txrx(sc, devi->cs, devi->mode, buf_out[i]);
366 
367 	/* Return pins to mode default */
368 	if ((devi->mode == SPIBUS_MODE_CPOL) ||
369 	    (devi->mode == SPIBUS_MODE_CPHA)) {
370 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
371 		    sc->sc_sclk, 1);
372 	} else {
373 		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
374 		    sc->sc_sclk, 0);
375 	}
376 
377 	gpio_spi_chip_deactivate(sc, devi->cs);
378 
379 	return (0);
380 }
381 
382 static device_method_t gpio_spi_methods[] = {
383 	/* Device interface */
384 	DEVMETHOD(device_probe,		gpio_spi_probe),
385 	DEVMETHOD(device_attach,	gpio_spi_attach),
386 	DEVMETHOD(device_detach,	gpio_spi_detach),
387 
388 	DEVMETHOD(spibus_transfer,	gpio_spi_transfer),
389 
390 	{0, 0}
391 };
392 
393 static driver_t gpio_spi_driver = {
394 	"gpiospi",
395 	gpio_spi_methods,
396 	sizeof(struct gpio_spi_softc),
397 };
398 
399 DRIVER_MODULE(gpiospi, gpiobus, gpio_spi_driver, 0, 0);
400 DRIVER_MODULE(spibus, gpiospi, spibus_driver, 0, 0);
401 MODULE_DEPEND(spi, gpiospi, 1, 1, 1);
402 MODULE_DEPEND(gpiobus, gpiospi, 1, 1, 1);
403