]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/gpio/gpiospi.c
Import libucl 20160812
[FreeBSD/FreeBSD.git] / sys / dev / gpio / gpiospi.c
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                 } else {
297                         /* If mode 0 or 3 */
298
299                         /* first step */
300                         GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
301                             sc->sc_mosi, (data & mask)?1:0);
302                         GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
303                             sc->sc_sclk, 1);
304                         gpio_delay(sc);
305                         /* second step */
306                         if (sc->sc_miso != 0xff) {
307                                 GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev,
308                                     sc->sc_miso, &bit);
309                                 out |= bit?mask:0;
310                         }
311                          /* Data captured */
312                         gpio_delay(sc);
313                         GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
314                             sc->sc_sclk, 0);
315                 }
316         }
317
318         return (out & 0xff);
319 }
320
321 static int
322 gpio_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
323 {
324         struct gpio_spi_softc *sc;
325         uint8_t *buf_in, *buf_out;
326         struct spibus_ivar *devi = SPIBUS_IVAR(child);
327         int i;
328
329         sc = device_get_softc(dev);
330
331         KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 
332             ("TX/RX command sizes should be equal"));
333         KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 
334             ("TX/RX data sizes should be equal"));
335
336         gpio_spi_chip_activate(sc, devi->cs);
337
338         /* Preset pins */
339         if ((devi->mode == SPIBUS_MODE_CPOL) ||
340             (devi->mode == SPIBUS_MODE_CPHA)) {
341                 GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
342                     sc->sc_sclk, 1);
343         } else {
344                 GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
345                     sc->sc_sclk, 0);
346         }
347
348         /*
349          * Transfer command
350          */
351         buf_out = (uint8_t *)cmd->tx_cmd;
352         buf_in = (uint8_t *)cmd->rx_cmd;
353
354         for (i = 0; i < cmd->tx_cmd_sz; i++)
355                 buf_in[i] = gpio_spi_txrx(sc, devi->cs, devi->mode, buf_out[i]);
356
357         /*
358          * Receive/transmit data (depends on command)
359          */
360         buf_out = (uint8_t *)cmd->tx_data;
361         buf_in = (uint8_t *)cmd->rx_data;
362         for (i = 0; i < cmd->tx_data_sz; i++)
363                 buf_in[i] = gpio_spi_txrx(sc, devi->cs, devi->mode, buf_out[i]);
364
365         /* Return pins to mode default */
366         if ((devi->mode == SPIBUS_MODE_CPOL) ||
367             (devi->mode == SPIBUS_MODE_CPHA)) {
368                 GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
369                     sc->sc_sclk, 1);
370         } else {
371                 GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev,
372                     sc->sc_sclk, 0);
373         }
374
375         gpio_spi_chip_deactivate(sc, devi->cs);
376
377         return (0);
378 }
379
380 static device_method_t gpio_spi_methods[] = {
381         /* Device interface */
382         DEVMETHOD(device_probe,         gpio_spi_probe),
383         DEVMETHOD(device_attach,        gpio_spi_attach),
384         DEVMETHOD(device_detach,        gpio_spi_detach),
385
386         DEVMETHOD(spibus_transfer,      gpio_spi_transfer),
387
388         {0, 0}
389 };
390
391 static driver_t gpio_spi_driver = {
392         "gpiospi",
393         gpio_spi_methods,
394         sizeof(struct gpio_spi_softc),
395 };
396
397 static devclass_t gpio_spi_devclass;
398
399 DRIVER_MODULE(gpiospi, gpiobus, gpio_spi_driver, gpio_spi_devclass, 0, 0);
400 DRIVER_MODULE(spibus, gpiospi, spibus_driver, spibus_devclass, 0, 0);
401 MODULE_DEPEND(spi, gpiospi, 1, 1, 1);
402 MODULE_DEPEND(gpiobus, gpiospi, 1, 1, 1);