1/*-
2 * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@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#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30#include "opt_acpi.h"
31
32#include <sys/param.h>
33#include <sys/bus.h>
34#include <sys/kernel.h>
35#include <sys/module.h>
36#include <sys/proc.h>
37#include <sys/rman.h>
38
39#include <machine/bus.h>
40#include <machine/resource.h>
41
42#include <dev/spibus/spi.h>
43#include <dev/spibus/spibusvar.h>
44
45#include <contrib/dev/acpica/include/acpi.h>
46#include <contrib/dev/acpica/include/accommon.h>
47
48#include <dev/acpica/acpivar.h>
49
50#include "spibus_if.h"
51
52/**
53 *	Macros for driver mutex locking
54 */
55#define	INTELSPI_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
56#define	INTELSPI_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
57#define	INTELSPI_LOCK_INIT(_sc)		\
58	mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
59	    "intelspi", MTX_DEF)
60#define	INTELSPI_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
61#define	INTELSPI_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
62#define	INTELSPI_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
63
64#define INTELSPI_WRITE(_sc, _off, _val)		\
65    bus_write_4((_sc)->sc_mem_res, (_off), (_val))
66#define INTELSPI_READ(_sc, _off)			\
67    bus_read_4((_sc)->sc_mem_res, (_off))
68
69#define	INTELSPI_BUSY		0x1
70#define	TX_FIFO_THRESHOLD	2
71#define	RX_FIFO_THRESHOLD	2
72#define	CLOCK_DIV_10MHZ		5
73#define	DATA_SIZE_8BITS		8
74
75#define	CS_LOW		0
76#define	CS_HIGH		1
77
78#define	INTELSPI_SSPREG_SSCR0	 	0x0
79#define	 SSCR0_SCR(n)				(((n) - 1) << 8)
80#define	 SSCR0_SSE				(1 << 7)
81#define	 SSCR0_FRF_SPI				(0 << 4)
82#define	 SSCR0_DSS(n)				(((n) - 1) << 0)
83#define	INTELSPI_SSPREG_SSCR1	 	0x4
84#define	 SSCR1_TINTE				(1 << 19)
85#define	 SSCR1_RFT(n)				(((n) - 1) << 10)
86#define	 SSCR1_RFT_MASK				(0xf << 10)
87#define	 SSCR1_TFT(n)				(((n) - 1) << 6)
88#define	 SSCR1_SPI_SPH				(1 << 4)
89#define	 SSCR1_SPI_SPO				(1 << 3)
90#define	 SSCR1_MODE_MASK				(SSCR1_SPI_SPO | SSCR1_SPI_SPH)
91#define	 SSCR1_MODE_0				(0)
92#define	 SSCR1_MODE_1				(SSCR1_SPI_SPH)
93#define	 SSCR1_MODE_2				(SSCR1_SPI_SPO)
94#define	 SSCR1_MODE_3				(SSCR1_SPI_SPO | SSCR1_SPI_SPH)
95#define	 SSCR1_TIE				(1 << 1)
96#define	 SSCR1_RIE				(1 << 0)
97#define	INTELSPI_SSPREG_SSSR	 	0x8
98#define	 SSSR_RFL_MASK				(0xf << 12)
99#define	 SSSR_TFL_MASK				(0xf << 8)
100#define	 SSSR_RNE				(1 << 3)
101#define	 SSSR_TNF				(1 << 2)
102#define	INTELSPI_SSPREG_SSITR	 	0xC
103#define	INTELSPI_SSPREG_SSDR	 	0x10
104#define	INTELSPI_SSPREG_SSTO	 	0x28
105#define	INTELSPI_SSPREG_SSPSP	 	0x2C
106#define	INTELSPI_SSPREG_SSTSA	 	0x30
107#define	INTELSPI_SSPREG_SSRSA	 	0x34
108#define	INTELSPI_SSPREG_SSTSS	 	0x38
109#define	INTELSPI_SSPREG_SSACD	 	0x3C
110#define	INTELSPI_SSPREG_ITF	 	0x40
111#define	INTELSPI_SSPREG_SITF	 	0x44
112#define	INTELSPI_SSPREG_SIRF	 	0x48
113#define	INTELSPI_SSPREG_PRV_CLOCK_PARAMS	0x400
114#define	INTELSPI_SSPREG_RESETS	 	0x404
115#define	INTELSPI_SSPREG_GENERAL	 	0x408
116#define	INTELSPI_SSPREG_SSP_REG	 	0x40C
117#define	INTELSPI_SSPREG_SPI_CS_CTRL	 0x418
118#define	 SPI_CS_CTRL_CS_MASK			(3)
119#define	 SPI_CS_CTRL_SW_MODE			(1 << 0)
120#define	 SPI_CS_CTRL_HW_MODE			(1 << 0)
121#define	 SPI_CS_CTRL_CS_HIGH			(1 << 1)
122#define	 SPI_CS_CTRL_CS_LOW			(0 << 1)
123
124struct intelspi_softc {
125	ACPI_HANDLE		sc_handle;
126	device_t		sc_dev;
127	struct mtx		sc_mtx;
128	int			sc_mem_rid;
129	struct resource		*sc_mem_res;
130	int			sc_irq_rid;
131	struct resource		*sc_irq_res;
132	void			*sc_irq_ih;
133	struct spi_command	*sc_cmd;
134	uint32_t		sc_len;
135	uint32_t		sc_read;
136	uint32_t		sc_flags;
137	uint32_t		sc_written;
138};
139
140static int	intelspi_probe(device_t dev);
141static int	intelspi_attach(device_t dev);
142static int	intelspi_detach(device_t dev);
143static void	intelspi_intr(void *);
144
145static int
146intelspi_txfifo_full(struct intelspi_softc *sc)
147{
148	uint32_t sssr;
149
150	INTELSPI_ASSERT_LOCKED(sc);
151
152	sssr = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
153	if (sssr & SSSR_TNF)
154		return (0);
155
156	return (1);
157}
158
159static int
160intelspi_rxfifo_empty(struct intelspi_softc *sc)
161{
162	uint32_t sssr;
163
164	INTELSPI_ASSERT_LOCKED(sc);
165
166	sssr = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
167	if (sssr & SSSR_RNE)
168		return (0);
169	else
170		return (1);
171}
172
173static void
174intelspi_fill_tx_fifo(struct intelspi_softc *sc)
175{
176	struct spi_command *cmd;
177	uint32_t written;
178	uint8_t *data;
179
180	INTELSPI_ASSERT_LOCKED(sc);
181
182	cmd = sc->sc_cmd;
183	while (sc->sc_written < sc->sc_len &&
184	    !intelspi_txfifo_full(sc)) {
185		data = (uint8_t *)cmd->tx_cmd;
186		written = sc->sc_written++;
187
188		if (written >= cmd->tx_cmd_sz) {
189			data = (uint8_t *)cmd->tx_data;
190			written -= cmd->tx_cmd_sz;
191		}
192		INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSDR, data[written]);
193	}
194}
195
196static void
197intelspi_drain_rx_fifo(struct intelspi_softc *sc)
198{
199	struct spi_command *cmd;
200	uint32_t  read;
201	uint8_t *data;
202
203	INTELSPI_ASSERT_LOCKED(sc);
204
205	cmd = sc->sc_cmd;
206	while (sc->sc_read < sc->sc_len &&
207	    !intelspi_rxfifo_empty(sc)) {
208		data = (uint8_t *)cmd->rx_cmd;
209		read = sc->sc_read++;
210		if (read >= cmd->rx_cmd_sz) {
211			data = (uint8_t *)cmd->rx_data;
212			read -= cmd->rx_cmd_sz;
213		}
214		data[read] = INTELSPI_READ(sc, INTELSPI_SSPREG_SSDR) & 0xff;
215	}
216}
217
218static int
219intelspi_transaction_done(struct intelspi_softc *sc)
220{
221	int txfifo_empty;
222	uint32_t sssr;
223
224	INTELSPI_ASSERT_LOCKED(sc);
225
226	if (sc->sc_written != sc->sc_len ||
227	    sc->sc_read != sc->sc_len)
228		return (0);
229
230	sssr = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
231	txfifo_empty = ((sssr & SSSR_TFL_MASK) == 0) &&
232		(sssr & SSSR_TNF);
233
234	if (txfifo_empty && !(sssr & SSSR_RNE))
235		return (1);
236
237	return (0);
238}
239
240static int
241intelspi_transact(struct intelspi_softc *sc)
242{
243
244	INTELSPI_ASSERT_LOCKED(sc);
245
246	/* TX - Fill up the FIFO. */
247	intelspi_fill_tx_fifo(sc);
248
249	/* RX - Drain the FIFO. */
250	intelspi_drain_rx_fifo(sc);
251
252	/* Check for end of transfer. */
253	return intelspi_transaction_done(sc);
254}
255
256static void
257intelspi_intr(void *arg)
258{
259	struct intelspi_softc *sc;
260	uint32_t reg;
261
262	sc = (struct intelspi_softc *)arg;
263
264	INTELSPI_LOCK(sc);
265	if ((sc->sc_flags & INTELSPI_BUSY) == 0) {
266		INTELSPI_UNLOCK(sc);
267		return;
268	}
269
270	/* Check if SSP if off */
271	reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SSSR);
272	if (reg == 0xffffffffU) {
273		INTELSPI_UNLOCK(sc);
274		return;
275	}
276
277	/* Check for end of transfer. */
278	if (intelspi_transact(sc)) {
279		/* Disable interrupts */
280		reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
281		reg &= ~(SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
282		INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, reg);
283		wakeup(sc->sc_dev);
284	}
285
286	INTELSPI_UNLOCK(sc);
287}
288
289static void
290intelspi_init(struct intelspi_softc *sc)
291{
292	uint32_t reg;
293
294	INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, 0);
295
296	/* Manual CS control */
297	reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SPI_CS_CTRL);
298	reg &= ~(SPI_CS_CTRL_CS_MASK);
299	reg |= (SPI_CS_CTRL_SW_MODE | SPI_CS_CTRL_CS_HIGH);
300	INTELSPI_WRITE(sc, INTELSPI_SSPREG_SPI_CS_CTRL, reg);
301
302	/* Set TX/RX FIFO IRQ threshold levels */
303	reg = SSCR1_TFT(TX_FIFO_THRESHOLD) | SSCR1_RFT(RX_FIFO_THRESHOLD);
304	/*
305	 * Set SPI mode. This should be part of transaction or sysctl
306	 */
307	reg |= SSCR1_MODE_0;
308	INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, reg);
309
310	/*
311	 * Parent clock on Minowboard Turbot is 50MHz
312	 * divide it by 5 to set to more or less reasonable
313	 * value. But this should be part of transaction config
314	 * or sysctl
315	 */
316	reg = SSCR0_SCR(CLOCK_DIV_10MHZ);
317	/* Put SSP in SPI mode */
318	reg |= SSCR0_FRF_SPI;
319	/* Data size */
320	reg |= SSCR0_DSS(DATA_SIZE_8BITS);
321	/* Enable SSP */
322	reg |= SSCR0_SSE;
323	INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR0, reg);
324}
325
326static void
327intelspi_set_cs(struct intelspi_softc *sc, int level)
328{
329	uint32_t reg;
330
331	reg = INTELSPI_READ(sc, INTELSPI_SSPREG_SPI_CS_CTRL);
332	reg &= ~(SPI_CS_CTRL_CS_MASK);
333	reg |= SPI_CS_CTRL_SW_MODE;
334
335	if (level == CS_HIGH)
336		reg |= SPI_CS_CTRL_CS_HIGH;
337	else
338		reg |= SPI_CS_CTRL_CS_LOW;
339
340	INTELSPI_WRITE(sc, INTELSPI_SSPREG_SPI_CS_CTRL, reg);
341}
342
343static int
344intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd)
345{
346	struct intelspi_softc *sc;
347	int err;
348	uint32_t sscr1;
349
350	sc = device_get_softc(dev);
351	err = 0;
352
353	KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
354	    ("TX/RX command sizes should be equal"));
355	KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
356	    ("TX/RX data sizes should be equal"));
357
358	INTELSPI_LOCK(sc);
359
360	/* If the controller is in use wait until it is available. */
361	while (sc->sc_flags & INTELSPI_BUSY) {
362		err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0);
363		if (err == EINTR) {
364			INTELSPI_UNLOCK(sc);
365			return (err);
366		}
367	}
368
369	/* Now we have control over SPI controller. */
370	sc->sc_flags = INTELSPI_BUSY;
371
372	/* Save a pointer to the SPI command. */
373	sc->sc_cmd = cmd;
374	sc->sc_read = 0;
375	sc->sc_written = 0;
376	sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;
377
378	/* Enable CS */
379	intelspi_set_cs(sc, CS_LOW);
380	/* Transfer as much as possible to FIFOs */
381	if (!intelspi_transact(sc)) {
382		/* If FIFO is not large enough - enable interrupts */
383		sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
384		sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
385		INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1);
386
387		/* and wait for transaction to complete */
388		err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2);
389	}
390
391	/* de-asser CS */
392	intelspi_set_cs(sc, CS_HIGH);
393
394	/* Clear transaction details */
395	sc->sc_cmd = NULL;
396	sc->sc_read = 0;
397	sc->sc_written = 0;
398	sc->sc_len = 0;
399
400	/* Make sure the SPI engine and interrupts are disabled. */
401	sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1);
402	sscr1 &= ~(SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE);
403	INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1);
404
405	/* Release the controller and wakeup the next thread waiting for it. */
406	sc->sc_flags = 0;
407	wakeup_one(dev);
408	INTELSPI_UNLOCK(sc);
409
410	/*
411	 * Check for transfer timeout.  The SPI controller doesn't
412	 * return errors.
413	 */
414	if (err == EWOULDBLOCK) {
415		device_printf(sc->sc_dev, "transfer timeout\n");
416		err = EIO;
417	}
418
419	return (err);
420}
421
422static int
423intelspi_probe(device_t dev)
424{
425	static char *gpio_ids[] = { "80860F0E", NULL };
426
427	if (acpi_disabled("spi") ||
428	    ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL)
429	return (ENXIO);
430
431	device_set_desc(dev, "Intel SPI Controller");
432	return (0);
433}
434
435static int
436intelspi_attach(device_t dev)
437{
438	struct intelspi_softc	*sc;
439
440	sc = device_get_softc(dev);
441	sc->sc_dev = dev;
442	sc->sc_handle = acpi_get_handle(dev);
443
444	INTELSPI_LOCK_INIT(sc);
445
446	sc->sc_mem_rid = 0;
447	sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev,
448	    SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE);
449	if (sc->sc_mem_res == NULL) {
450		device_printf(dev, "can't allocate memory resource\n");
451		goto error;
452	}
453
454	sc->sc_irq_rid = 0;
455	sc->sc_irq_res = bus_alloc_resource_any(sc->sc_dev,
456	    SYS_RES_IRQ, &sc->sc_irq_rid, RF_ACTIVE);
457	if (sc->sc_irq_res == NULL) {
458		device_printf(dev, "can't allocate IRQ resource\n");
459		goto error;
460	}
461
462	/* Hook up our interrupt handler. */
463	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
464	    NULL, intelspi_intr, sc, &sc->sc_irq_ih)) {
465		device_printf(dev, "cannot setup the interrupt handler\n");
466		goto error;
467	}
468
469	intelspi_init(sc);
470
471	device_add_child(dev, "spibus", -1);
472
473	return (bus_generic_attach(dev));
474
475error:
476	INTELSPI_LOCK_DESTROY(sc);
477
478	if (sc->sc_mem_res != NULL)
479		bus_release_resource(dev, SYS_RES_MEMORY,
480		    sc->sc_mem_rid, sc->sc_mem_res);
481
482	if (sc->sc_irq_res != NULL)
483		bus_release_resource(dev, SYS_RES_IRQ,
484		    sc->sc_irq_rid, sc->sc_irq_res);
485
486	return (ENXIO);
487}
488
489static int
490intelspi_detach(device_t dev)
491{
492	struct intelspi_softc	*sc;
493
494	sc = device_get_softc(dev);
495
496	INTELSPI_LOCK_DESTROY(sc);
497
498	if (sc->sc_irq_ih)
499		bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_ih);
500
501	if (sc->sc_mem_res != NULL)
502		bus_release_resource(dev, SYS_RES_MEMORY,
503		    sc->sc_mem_rid, sc->sc_mem_res);
504
505	if (sc->sc_irq_res != NULL)
506		bus_release_resource(dev, SYS_RES_IRQ,
507		    sc->sc_irq_rid, sc->sc_irq_res);
508
509	return (bus_generic_detach(dev));
510}
511
512static device_method_t intelspi_methods[] = {
513	/* Device interface */
514	DEVMETHOD(device_probe, intelspi_probe),
515	DEVMETHOD(device_attach, intelspi_attach),
516	DEVMETHOD(device_detach, intelspi_detach),
517
518	/* SPI interface */
519	DEVMETHOD(spibus_transfer,	intelspi_transfer),
520
521	DEVMETHOD_END
522};
523
524static driver_t intelspi_driver = {
525	"spi",
526	intelspi_methods,
527	sizeof(struct intelspi_softc),
528};
529
530static devclass_t intelspi_devclass;
531DRIVER_MODULE(intelspi, acpi, intelspi_driver, intelspi_devclass, 0, 0);
532MODULE_DEPEND(intelspi, acpi, 1, 1, 1);
533MODULE_DEPEND(intelspi, spibus, 1, 1, 1);
534