Module Name:    src
Committed By:   hkenken
Date:           Mon Aug 19 11:41:36 UTC 2019

Modified Files:
        src/sys/arch/arm/imx: imx51_spi.c imx51reg.h imxspi.c imxspivar.h
        src/sys/arch/arm/imx/fdt: files.imx6
        src/sys/arch/evbarm/conf: IMX
        src/sys/arch/evbarm/netwalker: netwalker_spi.c
Added Files:
        src/sys/arch/arm/imx/fdt: imx6_spi.c

Log Message:
Add support SPI driver for i.MX6.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/imx/imx51_spi.c \
    src/sys/arch/arm/imx/imxspivar.h
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/imx/imx51reg.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/imx/imxspi.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/imx/fdt/files.imx6
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/fdt/imx6_spi.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbarm/conf/IMX
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/netwalker/netwalker_spi.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/imx/imx51_spi.c
diff -u src/sys/arch/arm/imx/imx51_spi.c:1.1 src/sys/arch/arm/imx/imx51_spi.c:1.2
--- src/sys/arch/arm/imx/imx51_spi.c:1.1	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imx51_spi.c	Mon Aug 19 11:41:36 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: imx51_spi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+/*	$NetBSD: imx51_spi.c,v 1.2 2019/08/19 11:41:36 hkenken Exp $	*/
 
 /*-
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx51_spi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx51_spi.c,v 1.2 2019/08/19 11:41:36 hkenken Exp $");
 
 #include "locators.h"
 #include "opt_imx.h"
@@ -43,7 +43,8 @@ __KERNEL_RCSID(0, "$NetBSD: imx51_spi.c,
 #include <arm/imx/imx51_ccmvar.h>
 
 struct imx51spi_softc {
-	struct imxspi_softc sc_spi;
+	struct imxspi_softc sc_spi; /* Must be first */
+
 	struct spi_chipset_tag sc_tag;
 };
 
@@ -74,26 +75,39 @@ imxspi_match(device_t parent, cfdata_t c
 void
 imxspi_attach(device_t parent, device_t self, void *aux)
 {
-	struct imx51spi_softc *sc = device_private(self);
+	struct imx51spi_softc *isc = device_private(self);
+	struct imxspi_softc *sc = &isc->sc_spi;
 	struct axi_attach_args *aa = aux;
 	struct imxspi_attach_args saa;
 	int cf_flags = device_cfdata(self)->cf_flags;
+	bus_addr_t addr;
+	bus_size_t size;
+	int error;
+
+	addr = aa->aa_addr;
+	size = aa->aa_size;
+	if (size <= 0)
+		size = SPI_SIZE;
 
 	sc->sc_tag.cookie = sc;
 	sc->sc_tag.spi_cs_enable = imxspi_cs_enable;
 	sc->sc_tag.spi_cs_disable = imxspi_cs_disable;
 
-	saa.saa_iot = aa->aa_iot;
-	saa.saa_addr = aa->aa_addr;
-	saa.saa_size = aa->aa_size;
-	saa.saa_irq = aa->aa_irq;
-	saa.saa_enhanced = cf_flags;
-
-	saa.saa_nslaves = IMXSPINSLAVES;
-	saa.saa_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT);
-	saa.saa_tag = &sc->sc_tag;
+	sc->sc_iot = aa->aa_iot;
+	sc->sc_enhanced = cf_flags;
 
-	sc->sc_spi.sc_dev = self;
+	sc->sc_nslaves = IMXSPINSLAVES;
+	sc->sc_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT);
+	sc->sc_tag = &sc->sc_tag;
+
+	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
+		aprint_error_dev(sc->sc_dev, "couldn't map registers\n");
+		return;
+	}
+
+	/* enable device interrupts */
+	sc->sc_ih = intr_establish(aa->aa_irq, IPL_BIO, IST_LEVEL,
+	    imxspi_intr, sc);
 
-	imxspi_attach_common(parent, &sc->sc_spi, &saa);
+	imxspi_attach_common(self);
 }
Index: src/sys/arch/arm/imx/imxspivar.h
diff -u src/sys/arch/arm/imx/imxspivar.h:1.1 src/sys/arch/arm/imx/imxspivar.h:1.2
--- src/sys/arch/arm/imx/imxspivar.h:1.1	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxspivar.h	Mon Aug 19 11:41:36 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: imxspivar.h,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+/*	$NetBSD: imxspivar.h,v 1.2 2019/08/19 11:41:36 hkenken Exp $	*/
 
 /*
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -38,21 +38,10 @@ typedef struct spi_chipset_tag {
 	int (*spi_cs_disable)(void *, int);
 } *spi_chipset_tag_t;
 
-struct imxspi_attach_args {
-	bus_space_tag_t saa_iot;
-	bus_addr_t saa_addr;
-	bus_size_t saa_size;
-	int saa_irq;
-
-	spi_chipset_tag_t saa_tag;
-	int saa_nslaves;
-	unsigned long saa_freq;
-
-	int saa_enhanced;
-};
-
 struct imxspi_softc {
 	device_t sc_dev;
+	int sc_phandle;
+
 	bus_space_tag_t  sc_iot;
 	bus_space_handle_t sc_ioh;
 	spi_chipset_tag_t sc_tag;
@@ -66,10 +55,12 @@ struct imxspi_softc {
 	bool  sc_running;
 	SIMPLEQ_HEAD(,spi_transfer) sc_q;
 
+	int sc_nslaves;
 	int sc_enhanced;
 };
 
-int imxspi_attach_common(device_t, struct imxspi_softc *, void *);
+int imxspi_attach_common(device_t);
+int imxspi_intr(void *);
 
 /*
  * defined in machine dependent code

Index: src/sys/arch/arm/imx/imx51reg.h
diff -u src/sys/arch/arm/imx/imx51reg.h:1.7 src/sys/arch/arm/imx/imx51reg.h:1.8
--- src/sys/arch/arm/imx/imx51reg.h:1.7	Thu May  7 04:37:29 2015
+++ src/sys/arch/arm/imx/imx51reg.h	Mon Aug 19 11:41:36 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: imx51reg.h,v 1.7 2015/05/07 04:37:29 hkenken Exp $ */
+/* $NetBSD: imx51reg.h,v 1.8 2019/08/19 11:41:36 hkenken Exp $ */
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -140,7 +140,6 @@
 
 #define	ECSPI1_BASE	(AIPSTZ1_BASE + 0x00010000)
 #define	ECSPI2_BASE	(AIPSTZ2_BASE + 0x03fac000)
-#define	ECSPI_SIZE	0x4000
 
 #define	SSI1_BASE	(AIPSTZ2_BASE + 0x03fcc000)
 #define	SSI2_BASE	(AIPSTZ1_BASE + 0x00014000)

Index: src/sys/arch/arm/imx/imxspi.c
diff -u src/sys/arch/arm/imx/imxspi.c:1.4 src/sys/arch/arm/imx/imxspi.c:1.5
--- src/sys/arch/arm/imx/imxspi.c:1.4	Tue Aug 13 17:03:10 2019
+++ src/sys/arch/arm/imx/imxspi.c	Mon Aug 19 11:41:36 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: imxspi.c,v 1.4 2019/08/13 17:03:10 tnn Exp $	*/
+/*	$NetBSD: imxspi.c,v 1.5 2019/08/19 11:41:36 hkenken Exp $	*/
 
 /*-
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -32,10 +32,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.4 2019/08/13 17:03:10 tnn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.5 2019/08/19 11:41:36 hkenken Exp $");
 
 #include "opt_imx.h"
 #include "opt_imxspi.h"
+#include "opt_fdt.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -52,11 +53,14 @@ __KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1
 #include <arm/imx/imxspivar.h>
 #include <arm/imx/imxspireg.h>
 
+#ifdef FDT
+#include <dev/fdt/fdtvar.h>
+#endif
+
 /* SPI service routines */
 static int imxspi_configure_enhanced(void *, int, int, int);
 static int imxspi_configure(void *, int, int, int);
 static int imxspi_transfer(void *, struct spi_transfer *);
-static int imxspi_intr(void *);
 
 /* internal stuff */
 void imxspi_done(struct imxspi_softc *, int);
@@ -78,30 +82,30 @@ int imxspi_debug = IMXSPI_DEBUG;
 #define	DPRINTFN(n,x)
 #endif
 
-int
-imxspi_attach_common(device_t parent, struct imxspi_softc *sc, void *aux)
+#ifdef FDT
+static struct spi_controller *
+imxspi_get_controller(device_t dev)
 {
-	struct imxspi_attach_args *saa = aux;
-	struct spibus_attach_args sba;
-	bus_addr_t addr = saa->saa_addr;
-	bus_size_t size = saa->saa_size;
+	struct imxspi_softc * const sc = device_private(dev);
 
-	sc->sc_iot = saa->saa_iot;
-	sc->sc_freq = saa->saa_freq;
-	sc->sc_tag = saa->saa_tag;
-	sc->sc_enhanced = saa->saa_enhanced;
-	if (size <= 0)
-		size = SPI_SIZE;
-
-	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
-		aprint_error_dev(sc->sc_dev, "couldn't map registers\n");
-		return 1;
-	}
+	return &sc->sc_spi;
+}
+
+static const struct fdtbus_spi_controller_func imxspi_funcs = {
+	.get_controller = imxspi_get_controller
+};
+#endif
+
+int
+imxspi_attach_common(device_t self)
+{
+	struct imxspi_softc * const sc = device_private(self);
 
-	aprint_normal(": i.MX %sCSPI Controller (clock %ld Hz)\n",
+	aprint_normal("i.MX %sCSPI Controller (clock %ld Hz)\n",
 	    ((sc->sc_enhanced) ? "e" : ""), sc->sc_freq);
 
 	/* Initialize SPI controller */
+	sc->sc_dev = self;
 	sc->sc_spi.sct_cookie = sc;
 	if (sc->sc_enhanced)
 		sc->sc_spi.sct_configure = imxspi_configure_enhanced;
@@ -110,13 +114,10 @@ imxspi_attach_common(device_t parent, st
 	sc->sc_spi.sct_transfer = imxspi_transfer;
 
 	/* sc->sc_spi.sct_nslaves must have been initialized by machdep code */
-	sc->sc_spi.sct_nslaves = saa->saa_nslaves;
+	sc->sc_spi.sct_nslaves = sc->sc_nslaves;
 	if (!sc->sc_spi.sct_nslaves)
 		aprint_error_dev(sc->sc_dev, "no slaves!\n");
 
-	memset(&sba, 0, sizeof(sba));
-	sba.sba_controller = &sc->sc_spi;
-
 	/* initialize the queue */
 	SIMPLEQ_INIT(&sc->sc_q);
 
@@ -132,12 +133,19 @@ imxspi_attach_common(device_t parent, st
 
 	WRITE_REG(sc, PERIODREG, 0x0);
 
-	/* enable device interrupts */
-	sc->sc_ih = intr_establish(saa->saa_irq, IPL_BIO, IST_LEVEL,
-	    imxspi_intr, sc);
+#ifdef FDT
+	KASSERT(sc->sc_phandle != 0);
+
+	fdtbus_register_spi_controller(self, sc->sc_phandle, &imxspi_funcs);
+	(void) fdtbus_attach_spibus(self, sc->sc_phandle, spibus_print);
+#else
+	struct spibus_attach_args sba;
+	memset(&sba, 0, sizeof(sba));
+	sba.sba_controller = &sc->sc_spi;
 
 	/* attach slave devices */
 	(void)config_found_ia(sc->sc_dev, "spibus", &sba, spibus_print);
+#endif
 
 	return 0;
 }
@@ -363,7 +371,7 @@ imxspi_done(struct imxspi_softc *sc, int
 	imxspi_sched(sc);
 }
 
-static int
+int
 imxspi_intr(void *arg)
 {
 	struct imxspi_softc *sc = arg;

Index: src/sys/arch/arm/imx/fdt/files.imx6
diff -u src/sys/arch/arm/imx/fdt/files.imx6:1.5 src/sys/arch/arm/imx/fdt/files.imx6:1.6
--- src/sys/arch/arm/imx/fdt/files.imx6:1.5	Mon Aug 12 11:45:53 2019
+++ src/sys/arch/arm/imx/fdt/files.imx6	Mon Aug 19 11:41:36 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.imx6,v 1.5 2019/08/12 11:45:53 skrll Exp $
+#	$NetBSD: files.imx6,v 1.6 2019/08/19 11:41:36 hkenken Exp $
 #
 # Configuration info for the Freescale i.MX6
 #
@@ -76,3 +76,11 @@ device	imxi2c: motoi2c, i2cbus, i2cexec
 attach	imxi2c at fdt
 file	arch/arm/imx/imxi2c.c			imxi2c
 file	arch/arm/imx/fdt/imx6_i2c.c		imxi2c
+
+# SPI bus controlloer
+device  imxspi : spibus
+attach	imxspi at fdt with imxspi_fdt
+file    arch/arm/imx/imxspi.c			imxspi
+file	arch/arm/imx/fdt/imx6_spi.c		imxspi_fdt
+defparam opt_imxspi.h                   	IMXSPINSLAVES
+

Index: src/sys/arch/evbarm/conf/IMX
diff -u src/sys/arch/evbarm/conf/IMX:1.3 src/sys/arch/evbarm/conf/IMX:1.4
--- src/sys/arch/evbarm/conf/IMX:1.3	Mon Aug 12 11:46:39 2019
+++ src/sys/arch/evbarm/conf/IMX	Mon Aug 19 11:41:36 2019
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: IMX,v 1.3 2019/08/12 11:46:39 skrll Exp $
+#	$NetBSD: IMX,v 1.4 2019/08/19 11:41:36 hkenken Exp $
 #
 #	NXP(Freescale) I.MX family SoCs
 #
@@ -15,6 +15,7 @@ makeoptions	DTS="
 	imx6dl-hummingboard.dts
 	imx6q-hummingboard2.dts
 	imx6dl-hummingboard2.dts
+	imx6qp-sabresd.dts
 "
 
 options 	MULTIPROCESSOR
@@ -136,5 +137,14 @@ pci*		at ppb?
 imxi2c* 	at fdt?
 iic*		at imxi2c?
 
+# SPI
+imxspi*		at fdt?
+spi*		at imxspi?
+options		IMXSPINSLAVES=1
+
+# SPI NOR-Flash
+spiflash*	at spiflashbus?
+m25p*		at spi? slave ?
+
 cinclude "arch/evbarm/conf/IMX.local"
 

Index: src/sys/arch/evbarm/netwalker/netwalker_spi.c
diff -u src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.2 src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.3
--- src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.2	Wed Jul 24 12:33:18 2019
+++ src/sys/arch/evbarm/netwalker/netwalker_spi.c	Mon Aug 19 11:41:36 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: netwalker_spi.c,v 1.2 2019/07/24 12:33:18 hkenken Exp $	*/
+/*	$NetBSD: netwalker_spi.c,v 1.3 2019/08/19 11:41:36 hkenken Exp $	*/
 
 /*-
  * Copyright (c) 2009  Genetec Corporation.  All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netwalker_spi.c,v 1.2 2019/07/24 12:33:18 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netwalker_spi.c,v 1.3 2019/08/19 11:41:36 hkenken Exp $");
 
 #include "opt_imxspi.h"
 
@@ -45,9 +45,11 @@ __KERNEL_RCSID(0, "$NetBSD: netwalker_sp
 #include <arm/imx/imx51_iomuxreg.h>
 #include <arm/imx/imxgpiovar.h>
 #include <arm/imx/imxspivar.h>
+#include <arm/imx/imxspireg.h>
 
 struct imx51spi_softc {
-	struct imxspi_softc	sc_spi;
+	struct imxspi_softc	sc_spi; /* Must be first */
+
 	struct spi_chipset_tag	sc_tag;
 };
 
@@ -110,14 +112,22 @@ imxspi_match(device_t parent, cfdata_t c
 void
 imxspi_attach(device_t parent, device_t self, void *aux)
 {
-	struct imx51spi_softc *sc = device_private(self);
+	struct imx51spi_softc *isc = device_private(self);
+	struct imxspi_softc *sc = &isc->sc_spi;
 	struct axi_attach_args *aa = aux;
-	struct imxspi_attach_args saa;
 	int cf_flags = device_cfdata(self)->cf_flags;
+	bus_addr_t addr;
+	bus_size_t size;
+
+	addr = aa->aa_addr;
+	size = aa->aa_size;
+	if (size <= 0)
+		size = SPI_SIZE;
 
-	sc->sc_tag.cookie = sc;
+	isc->sc_tag.cookie = sc;
 
-	if (device_cfdata(self)->cf_unit == 0) {
+	switch (device_unit(self)) {
+	case 0:
 		/* CS 0 GPIO setting */
 		gpio_data_write(GPIO_NO(4, 24), GPIO_PIN_HIGH);
 		gpio_set_direction(GPIO_NO(4, 24), GPIO_PIN_INPUT);
@@ -135,21 +145,26 @@ imxspi_attach(device_t parent, device_t 
 		gpio_data_write(GPIO_NO(3, 0), GPIO_PIN_HIGH);
 		gpio_set_direction(GPIO_NO(3, 0), GPIO_PIN_INPUT);
 
-		sc->sc_tag.spi_cs_enable = imxspi_cs_enable;
-		sc->sc_tag.spi_cs_disable = imxspi_cs_disable;
+		isc->sc_tag.spi_cs_enable = imxspi_cs_enable;
+		isc->sc_tag.spi_cs_disable = imxspi_cs_disable;
+		break;
 	}
 
-	saa.saa_iot = aa->aa_iot;
-	saa.saa_addr = aa->aa_addr;
-	saa.saa_size = aa->aa_size;
-	saa.saa_irq = aa->aa_irq;
-	saa.saa_enhanced = cf_flags;
-
-	saa.saa_nslaves = IMXSPINSLAVES;
-	saa.saa_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT);
-	saa.saa_tag = &sc->sc_tag;
+	sc->sc_iot = aa->aa_iot;
+	sc->sc_enhanced = cf_flags;
+
+	sc->sc_nslaves = IMXSPINSLAVES;
+	sc->sc_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT);
+	sc->sc_tag = &isc->sc_tag;
+
+	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
+		aprint_error_dev(sc->sc_dev, "couldn't map registers\n");
+		return;
+	}
 
-	sc->sc_spi.sc_dev = self;
+	/* enable device interrupts */
+	sc->sc_ih = intr_establish(aa->aa_irq, IPL_BIO, IST_LEVEL,
+	    imxspi_intr, sc);
 
-	imxspi_attach_common(parent, &sc->sc_spi, &saa);
+	imxspi_attach_common(self);
 }

Added files:

Index: src/sys/arch/arm/imx/fdt/imx6_spi.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_spi.c:1.1
--- /dev/null	Mon Aug 19 11:41:36 2019
+++ src/sys/arch/arm/imx/fdt/imx6_spi.c	Mon Aug 19 11:41:36 2019
@@ -0,0 +1,156 @@
+/*	$NetBSD: imx6_spi.c,v 1.1 2019/08/19 11:41:36 hkenken Exp $	*/
+/*-
+ * Copyright (c) 2019 Genetec Corporation.  All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx6_spi.c,v 1.1 2019/08/19 11:41:36 hkenken Exp $");
+
+#include "opt_imxspi.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/gpio.h>
+
+#include <arm/imx/imxspivar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+struct imxspi_fdt_softc {
+	struct imxspi_softc sc_imxspi; /* Must be first */
+
+	struct spi_chipset_tag sc_tag;
+	struct clk *sc_clk;
+
+	struct fdtbus_gpio_pin **sc_pin_cs;
+};
+
+static const struct of_compat_data compat_data[] = {
+	{ "fsl,imx6q-ecspi",		true },
+	{ NULL }
+};
+
+CFATTACH_DECL_NEW(imxspi_fdt, sizeof(struct imxspi_fdt_softc),
+    imxspi_match, imxspi_attach, NULL, NULL);
+
+static int
+imxspi_cs_enable(void *arg, int slave)
+{
+	struct imxspi_fdt_softc * const sc = arg;
+	fdtbus_gpio_write(sc->sc_pin_cs[slave], 1);
+	return 0;
+}
+
+static int
+imxspi_cs_disable(void *arg, int slave)
+{
+	struct imxspi_fdt_softc * const sc = arg;
+	fdtbus_gpio_write(sc->sc_pin_cs[slave], 0);
+	return 0;
+}
+
+int
+imxspi_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compat_data(faa->faa_phandle, compat_data);
+}
+
+void
+imxspi_attach(device_t parent, device_t self, void *aux)
+{
+	struct imxspi_fdt_softc * const ifsc = device_private(self);
+	struct imxspi_softc * const sc = &ifsc->sc_imxspi;
+	struct fdt_attach_args * const faa = aux;
+	char intrstr[128];
+	const int phandle = faa->faa_phandle;
+	bus_addr_t addr;
+	bus_size_t size;
+	int error;
+
+	u_int nslaves;
+	error = of_getprop_uint32(phandle, "fsl,spi-num-chipselects", &nslaves);
+	if (error)
+		nslaves = IMXSPINSLAVES;
+
+	ifsc->sc_pin_cs = kmem_alloc(sizeof(struct fdtbus_gpio_pin *) * nslaves, KM_SLEEP);
+
+	for (int i = 0; i < nslaves; i++) {
+		ifsc->sc_pin_cs[i] = fdtbus_gpio_acquire_index(phandle, "cs-gpios", i,
+		    GPIO_PIN_OUTPUT);
+	}
+
+	ifsc->sc_clk = fdtbus_clock_get_index(phandle, 0);
+	if (ifsc->sc_clk == NULL) {
+		aprint_error(": couldn't get clock\n");
+		return;
+	}
+
+	error = clk_enable(ifsc->sc_clk);
+	if (error) {
+		aprint_error_dev(sc->sc_dev, "couldn't enable: %d\n", error);
+		return;
+	}
+
+	ifsc->sc_tag.cookie = ifsc;
+	ifsc->sc_tag.spi_cs_enable = imxspi_cs_enable;
+	ifsc->sc_tag.spi_cs_disable = imxspi_cs_disable;
+
+	sc->sc_phandle = phandle;
+	sc->sc_iot = faa->faa_bst;
+	sc->sc_enhanced = of_search_compatible(phandle, compat_data)->data;
+
+	sc->sc_nslaves = nslaves;
+	sc->sc_freq = clk_get_rate(ifsc->sc_clk);
+	sc->sc_tag = &ifsc->sc_tag;
+
+	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+		aprint_error(": couldn't get iomux registers\n");
+		return;
+	}
+
+	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
+		aprint_error_dev(sc->sc_dev, "couldn't map registers\n");
+		return;
+	}
+
+	if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
+		aprint_error_dev(self, "failed to decode interrupt\n");
+		return;
+	}
+
+	sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM,
+	    FDT_INTR_MPSAFE, imxspi_intr, &ifsc->sc_imxspi);
+	if (sc->sc_ih == NULL) {
+		aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+		    intrstr);
+		return;
+	}
+	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+	imxspi_attach_common(self);
+}

Reply via email to