1 /*-
2 * Copyright (c) 2017 Justin Hibbits <jhibbits@FreeBSD.org>
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, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/kernel.h>
32 #include <sys/lock.h>
33 #include <sys/malloc.h>
34 #include <sys/module.h>
35 #include <sys/mutex.h>
36
37 #include <machine/bus.h>
38
39 #include <dev/spibus/spi.h>
40 #include <dev/spibus/spibusvar.h>
41
42 #include <dev/ofw/ofw_bus.h>
43 #include <dev/ofw/ofw_bus_subr.h>
44
45 #include <powerpc/mpc85xx/mpc85xx.h>
46
47 #include "spibus_if.h"
48
49 /* TODO:
50 *
51 * Optimize FIFO reads and writes to do word-at-a-time instead of byte-at-a-time
52 */
53 #define ESPI_SPMODE 0x0
54 #define ESPI_SPMODE_EN 0x80000000
55 #define ESPI_SPMODE_LOOP 0x40000000
56 #define ESPI_SPMODE_HO_ADJ_M 0x00070000
57 #define ESPI_SPMODE_TXTHR_M 0x00003f00
58 #define ESPI_SPMODE_TXTHR_S 8
59 #define ESPI_SPMODE_RXTHR_M 0x0000001f
60 #define ESPI_SPMODE_RXTHR_S 0
61 #define ESPI_SPIE 0x4
62 #define ESPI_SPIE_RXCNT_M 0x3f000000
63 #define ESPI_SPIE_RXCNT_S 24
64 #define ESPI_SPIE_TXCNT_M 0x003f0000
65 #define ESPI_SPIE_TXCNT_S 16
66 #define ESPI_SPIE_TXE 0x00008000
67 #define ESPI_SPIE_DON 0x00004000
68 #define ESPI_SPIE_RXT 0x00002000
69 #define ESPI_SPIE_RXF 0x00001000
70 #define ESPI_SPIE_TXT 0x00000800
71 #define ESPI_SPIE_RNE 0x00000200
72 #define ESPI_SPIE_TNF 0x00000100
73 #define ESPI_SPIM 0x8
74 #define ESPI_SPCOM 0xc
75 #define ESPI_SPCOM_CS_M 0xc0000000
76 #define ESPI_SPCOM_CS_S 30
77 #define ESPI_SPCOM_RXDELAY 0x20000000
78 #define ESPI_SPCOM_DO 0x10000000
79 #define ESPI_SPCOM_TO 0x08000000
80 #define ESPI_SPCOM_HLD 0x04000000
81 #define ESPI_SPCOM_RXSKIP_M 0x00ff0000
82 #define ESPI_SPCOM_TRANLEN_M 0x0000ffff
83 #define ESPI_SPITF 0x10
84 #define ESPI_SPIRF 0x14
85 #define ESPI_SPMODE0 0x20
86 #define ESPI_SPMODE1 0x24
87 #define ESPI_SPMODE2 0x28
88 #define ESPI_SPMODE3 0x2c
89 #define ESPI_CSMODE_CI 0x80000000
90 #define ESPI_CSMODE_CP 0x40000000
91 #define ESPI_CSMODE_REV 0x20000000
92 #define ESPI_CSMODE_DIV16 0x10000000
93 #define ESPI_CSMODE_PM_M 0x0f000000
94 #define ESPI_CSMODE_PM_S 24
95 #define ESPI_CSMODE_ODD 0x00800000
96 #define ESPI_CSMODE_POL 0x00100000
97 #define ESPI_CSMODE_LEN_M 0x000f0000
98 #define ESPI_CSMODE_LEN(x) (x << 16)
99 #define ESPI_CSMODE_CSBEF_M 0x0000f000
100 #define ESPI_CSMODE_CSAFT_M 0x00000f00
101 #define ESPI_CSMODE_CSCG_M 0x000000f8
102 #define ESPI_CSMODE_CSCG(x) (x << 3)
103 #define ESPI_CSMODE(n) (ESPI_SPMODE0 + n * 4)
104
105 #define FSL_ESPI_WRITE(sc,off,val) bus_write_4(sc->sc_mem_res, off, val)
106 #define FSL_ESPI_READ(sc,off) bus_read_4(sc->sc_mem_res, off)
107 #define FSL_ESPI_WRITE_FIFO(sc,off,val) bus_write_1(sc->sc_mem_res, off, val)
108 #define FSL_ESPI_READ_FIFO(sc,off) bus_read_1(sc->sc_mem_res, off)
109
110 #define FSL_ESPI_LOCK(_sc) \
111 mtx_lock(&(_sc)->sc_mtx)
112 #define FSL_ESPI_UNLOCK(_sc) \
113 mtx_unlock(&(_sc)->sc_mtx)
114
115 struct fsl_espi_softc
116 {
117 device_t sc_dev;
118 struct resource *sc_mem_res;
119 struct resource *sc_irq_res;
120 struct mtx sc_mtx;
121 int sc_num_cs;
122 struct spi_command *sc_cmd;
123 uint32_t sc_len;
124 uint32_t sc_read;
125 uint32_t sc_flags;
126 #define FSL_ESPI_BUSY 0x00000001
127 uint32_t sc_written;
128 void * sc_intrhand;
129 };
130
131 static void fsl_espi_intr(void *);
132
133 static int
fsl_espi_probe(device_t dev)134 fsl_espi_probe(device_t dev)
135 {
136
137 if (!ofw_bus_status_okay(dev))
138 return (ENXIO);
139
140 if (!ofw_bus_is_compatible(dev, "fsl,mpc8536-espi"))
141 return (ENXIO);
142
143 device_set_desc(dev, "Freescale eSPI controller");
144
145 return (BUS_PROBE_DEFAULT);
146 }
147
148 static int
fsl_espi_attach(device_t dev)149 fsl_espi_attach(device_t dev)
150 {
151 struct fsl_espi_softc *sc;
152 int rid;
153 phandle_t node;
154
155 sc = device_get_softc(dev);
156 sc->sc_dev = dev;
157 node = ofw_bus_get_node(dev);
158
159 rid = 0;
160 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
161 RF_ACTIVE);
162 if (!sc->sc_mem_res) {
163 device_printf(dev, "cannot allocate memory resource\n");
164 return (ENXIO);
165 }
166
167 rid = 0;
168 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
169 RF_ACTIVE);
170 if (!sc->sc_irq_res) {
171 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
172 device_printf(dev, "cannot allocate interrupt\n");
173 return (ENXIO);
174 }
175
176 /* Hook up our interrupt handler. */
177 if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
178 NULL, fsl_espi_intr, sc, &sc->sc_intrhand)) {
179 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
180 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
181 device_printf(dev, "cannot setup the interrupt handler\n");
182 return (ENXIO);
183 }
184 if (OF_getencprop(node, "fsl,espi-num-chipselects",
185 &sc->sc_num_cs, sizeof(sc->sc_num_cs)) < 0 )
186 sc->sc_num_cs = 4;
187
188 mtx_init(&sc->sc_mtx, "fsl_espi", NULL, MTX_DEF);
189
190 /* Enable the SPI controller. */
191 FSL_ESPI_WRITE(sc, ESPI_SPMODE, ESPI_SPMODE_EN |
192 (16 << ESPI_SPMODE_TXTHR_S) | (15 << ESPI_SPMODE_RXTHR_S));
193
194 /* Disable all interrupts until we start transfers */
195 FSL_ESPI_WRITE(sc, ESPI_SPIM, 0);
196
197 device_add_child(dev, "spibus", DEVICE_UNIT_ANY);
198 bus_attach_children(dev);
199 return (0);
200 }
201
202 static int
fsl_espi_detach(device_t dev)203 fsl_espi_detach(device_t dev)
204 {
205 struct fsl_espi_softc *sc;
206
207 bus_generic_detach(dev);
208
209 sc = device_get_softc(dev);
210 FSL_ESPI_WRITE(sc, ESPI_SPMODE, 0);
211
212 sc = device_get_softc(dev);
213 mtx_destroy(&sc->sc_mtx);
214 if (sc->sc_intrhand)
215 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
216 if (sc->sc_irq_res)
217 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
218 if (sc->sc_mem_res)
219 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
220
221 return (0);
222 }
223
224 static void
fsl_espi_fill_fifo(struct fsl_espi_softc * sc)225 fsl_espi_fill_fifo(struct fsl_espi_softc *sc)
226 {
227 struct spi_command *cmd;
228 uint32_t spier, written;
229 uint8_t *data;
230
231 cmd = sc->sc_cmd;
232 spier = FSL_ESPI_READ(sc, ESPI_SPIE);
233 while (sc->sc_written < sc->sc_len &&
234 (spier & ESPI_SPIE_TNF)) {
235 data = (uint8_t *)cmd->tx_cmd;
236 written = sc->sc_written++;
237 if (written >= cmd->tx_cmd_sz) {
238 data = (uint8_t *)cmd->tx_data;
239 written -= cmd->tx_cmd_sz;
240 }
241 FSL_ESPI_WRITE_FIFO(sc, ESPI_SPITF, data[written]);
242 spier = FSL_ESPI_READ(sc, ESPI_SPIE);
243 }
244 }
245
246 static void
fsl_espi_drain_fifo(struct fsl_espi_softc * sc)247 fsl_espi_drain_fifo(struct fsl_espi_softc *sc)
248 {
249 struct spi_command *cmd;
250 uint32_t spier, read;
251 uint8_t *data;
252 uint8_t r;
253
254 cmd = sc->sc_cmd;
255 spier = FSL_ESPI_READ(sc, ESPI_SPIE);
256 while (sc->sc_read < sc->sc_len && (spier & ESPI_SPIE_RNE)) {
257 data = (uint8_t *)cmd->rx_cmd;
258 read = sc->sc_read++;
259 if (read >= cmd->rx_cmd_sz) {
260 data = (uint8_t *)cmd->rx_data;
261 read -= cmd->rx_cmd_sz;
262 }
263 r = FSL_ESPI_READ_FIFO(sc, ESPI_SPIRF);
264 data[read] = r;
265 spier = FSL_ESPI_READ(sc, ESPI_SPIE);
266 }
267 }
268
269 static void
fsl_espi_intr(void * arg)270 fsl_espi_intr(void *arg)
271 {
272 struct fsl_espi_softc *sc;
273 uint32_t spie;
274
275 sc = (struct fsl_espi_softc *)arg;
276 FSL_ESPI_LOCK(sc);
277
278 /* Filter stray interrupts. */
279 if ((sc->sc_flags & FSL_ESPI_BUSY) == 0) {
280 FSL_ESPI_UNLOCK(sc);
281 return;
282 }
283 spie = FSL_ESPI_READ(sc, ESPI_SPIE);
284 FSL_ESPI_WRITE(sc, ESPI_SPIE, spie);
285
286 /* TX - Fill up the FIFO. */
287 fsl_espi_fill_fifo(sc);
288
289 /* RX - Drain the FIFO. */
290 fsl_espi_drain_fifo(sc);
291
292 /* Check for end of transfer. */
293 if (spie & ESPI_SPIE_DON)
294 wakeup(sc->sc_dev);
295
296 FSL_ESPI_UNLOCK(sc);
297 }
298
299 static int
fsl_espi_transfer(device_t dev,device_t child,struct spi_command * cmd)300 fsl_espi_transfer(device_t dev, device_t child, struct spi_command *cmd)
301 {
302 struct fsl_espi_softc *sc;
303 u_long plat_clk;
304 uint32_t csmode, spi_clk, spi_mode;
305 int cs, err, pm;
306
307 sc = device_get_softc(dev);
308
309 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
310 ("TX/RX command sizes should be equal"));
311 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
312 ("TX/RX data sizes should be equal"));
313
314 /* Restrict transmit length to command max length */
315 if (cmd->tx_cmd_sz + cmd->tx_data_sz > ESPI_SPCOM_TRANLEN_M + 1) {
316 return (EINVAL);
317 }
318
319 /* Get the proper chip select for this child. */
320 spibus_get_cs(child, &cs);
321 if (cs < 0 || cs > sc->sc_num_cs) {
322 device_printf(dev,
323 "Invalid chip select %d requested by %s\n", cs,
324 device_get_nameunit(child));
325 return (EINVAL);
326 }
327 spibus_get_clock(child, &spi_clk);
328 spibus_get_mode(child, &spi_mode);
329
330 FSL_ESPI_LOCK(sc);
331
332 /* If the controller is in use wait until it is available. */
333 while (sc->sc_flags & FSL_ESPI_BUSY)
334 mtx_sleep(dev, &sc->sc_mtx, 0, "fsl_espi", 0);
335
336 /* Now we have control over SPI controller. */
337 sc->sc_flags = FSL_ESPI_BUSY;
338
339 /* Save a pointer to the SPI command. */
340 sc->sc_cmd = cmd;
341 sc->sc_read = 0;
342 sc->sc_written = 0;
343 sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;
344
345 plat_clk = mpc85xx_get_system_clock();
346 spi_clk = max(spi_clk, plat_clk / (16 * 16));
347 if (plat_clk == 0) {
348 device_printf(dev,
349 "unable to get platform clock, giving up.\n");
350 return (EINVAL);
351 }
352 csmode = 0;
353 if (plat_clk > spi_clk * 16 * 2) {
354 csmode |= ESPI_CSMODE_DIV16;
355 plat_clk /= 16;
356 }
357 pm = howmany(plat_clk, spi_clk * 2) - 1;
358 if (pm < 0)
359 pm = 1;
360 if (pm > 15)
361 pm = 15;
362
363 csmode |= (pm << ESPI_CSMODE_PM_S);
364 csmode |= ESPI_CSMODE_REV;
365 if (spi_mode == SPIBUS_MODE_CPOL || spi_mode == SPIBUS_MODE_CPOL_CPHA)
366 csmode |= ESPI_CSMODE_CI;
367 if (spi_mode == SPIBUS_MODE_CPHA || spi_mode == SPIBUS_MODE_CPOL_CPHA)
368 csmode |= ESPI_CSMODE_CP;
369 if (!(cs & SPIBUS_CS_HIGH))
370 csmode |= ESPI_CSMODE_POL;
371 csmode |= ESPI_CSMODE_LEN(7);/* Only deal with 8-bit characters. */
372 csmode |= ESPI_CSMODE_CSCG(1); /* XXX: Make this configurable? */
373 /* Configure transaction */
374 FSL_ESPI_WRITE(sc, ESPI_SPCOM, (cs << ESPI_SPCOM_CS_S) | (sc->sc_len - 1));
375 FSL_ESPI_WRITE(sc, ESPI_CSMODE(cs), csmode);
376 /* Enable interrupts we need. */
377 FSL_ESPI_WRITE(sc, ESPI_SPIM,
378 ESPI_SPIE_TXE | ESPI_SPIE_DON | ESPI_SPIE_RXF);
379
380 /* Wait for the transaction to complete. */
381 err = mtx_sleep(dev, &sc->sc_mtx, 0, "fsl_espi", hz * 2);
382 FSL_ESPI_WRITE(sc, ESPI_SPIM, 0);
383
384 /* Release the controller and wakeup the next thread waiting for it. */
385 sc->sc_flags = 0;
386 wakeup_one(dev);
387 FSL_ESPI_UNLOCK(sc);
388
389 /*
390 * Check for transfer timeout. The SPI controller doesn't
391 * return errors.
392 */
393 if (err == EWOULDBLOCK) {
394 device_printf(sc->sc_dev, "SPI error\n");
395 err = EIO;
396 }
397
398 return (err);
399 }
400
401 static phandle_t
fsl_espi_get_node(device_t bus,device_t dev)402 fsl_espi_get_node(device_t bus, device_t dev)
403 {
404
405 /* We only have one child, the SPI bus, which needs our own node. */
406 return (ofw_bus_get_node(bus));
407 }
408
409 static device_method_t fsl_espi_methods[] = {
410 /* Device interface */
411 DEVMETHOD(device_probe, fsl_espi_probe),
412 DEVMETHOD(device_attach, fsl_espi_attach),
413 DEVMETHOD(device_detach, fsl_espi_detach),
414
415 /* SPI interface */
416 DEVMETHOD(spibus_transfer, fsl_espi_transfer),
417
418 /* ofw_bus interface */
419 DEVMETHOD(ofw_bus_get_node, fsl_espi_get_node),
420
421 DEVMETHOD_END
422 };
423
424 static driver_t fsl_espi_driver = {
425 "spi",
426 fsl_espi_methods,
427 sizeof(struct fsl_espi_softc),
428 };
429
430 DRIVER_MODULE(fsl_espi, simplebus, fsl_espi_driver, 0, 0);
431