Module Name:    src
Committed By:   hkenken
Date:           Sat Mar 22 09:28:08 UTC 2014

Modified Files:
        src/sys/arch/arm/imx: files.imx51 imx51_ccm.c imx51_ccmreg.h
Added Files:
        src/sys/arch/arm/imx: imx51_spi.c imxcspireg.h imxecspireg.h imxspi.c
            imxspireg.h imxspivar.h

Log Message:
Add SPI driver.
i.MX51 have two eCSPI, and one CSPI.


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/imx/files.imx51
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/imx/imx51_ccm.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/imx/imx51_ccmreg.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/imx51_spi.c \
    src/sys/arch/arm/imx/imxcspireg.h src/sys/arch/arm/imx/imxecspireg.h \
    src/sys/arch/arm/imx/imxspi.c src/sys/arch/arm/imx/imxspireg.h \
    src/sys/arch/arm/imx/imxspivar.h

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/files.imx51
diff -u src/sys/arch/arm/imx/files.imx51:1.7 src/sys/arch/arm/imx/files.imx51:1.8
--- src/sys/arch/arm/imx/files.imx51:1.7	Sat Mar 22 05:19:18 2014
+++ src/sys/arch/arm/imx/files.imx51	Sat Mar 22 09:28:08 2014
@@ -1,4 +1,4 @@
-#	$NetBSD: files.imx51,v 1.7 2014/03/22 05:19:18 hkenken Exp $
+#	$NetBSD: files.imx51,v 1.8 2014/03/22 09:28:08 hkenken Exp $
 #
 # Configuration info for the Freescale i.MX51
 #
@@ -104,9 +104,15 @@ file	arch/arm/imx/imx51_esdhc.c		sdhc_ax
 # attach	imxi2c at aips with imxi2c_aips
 # file	arch/arm/imx/imxi2c_aips.c		imxi2c_aips
 
-# spi bus controlloer
-# device	imxspi: spibus
-# file	arch/arm/imx/imx51_spi.c		imxspi
+# SPI bus controlloer
+# attach of this driver need to be specified in paltform configuration
+# use flags to module version
+device  imxspi : spibus
+file    arch/arm/imx/imxspi.c			imxspi
+defparam opt_imxspi.h                   	IMXSPINSLAVES
+defparam opt_imxspi.h				IMXSPI_DEBUG
+# attach	imxspi at axi with imx51_spi
+# file	arch/arm/imx/imx51_spi.c		imx51_spi
 
 # Smart Direct Memory Access Controller
 # device	imxsdma: dmover_service, bus_dma_generic

Index: src/sys/arch/arm/imx/imx51_ccm.c
diff -u src/sys/arch/arm/imx/imx51_ccm.c:1.3 src/sys/arch/arm/imx/imx51_ccm.c:1.4
--- src/sys/arch/arm/imx/imx51_ccm.c:1.3	Wed Sep 19 07:28:38 2012
+++ src/sys/arch/arm/imx/imx51_ccm.c	Sat Mar 22 09:28:08 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: imx51_ccm.c,v 1.3 2012/09/19 07:28:38 bsh Exp $	*/
+/*	$NetBSD: imx51_ccm.c,v 1.4 2014/03/22 09:28:08 hkenken Exp $	*/
 /*
  * Copyright (c) 2010, 2011, 2012  Genetec Corporation.  All rights reserved.
  * Written by Hashimoto Kenichi for Genetec Corporation.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx51_ccm.c,v 1.3 2012/09/19 07:28:38 bsh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx51_ccm.c,v 1.4 2014/03/22 09:28:08 hkenken Exp $");
 
 #include <sys/types.h>
 #include <sys/time.h>
@@ -146,6 +146,7 @@ imx51_get_clock(enum imx51_clock clk)
 	uint32_t cacrr;	/* ARM clock root register */
 	uint32_t ccsr;
 	uint32_t cscdr1;
+	uint32_t cscdr2;
 	uint32_t cscmr1;
 	uint32_t cbcdr;
 	uint32_t cbcmr;
@@ -293,6 +294,26 @@ imx51_get_clock(enum imx51_clock clk)
 				break;
 			}
 		return freq;
+	case IMX51CLK_CSPI_CLK_ROOT:
+		cscmr1 = bus_space_read_4(iot, ioh, CCMC_CSCMR1);
+		cscdr2 = bus_space_read_4(iot, ioh, CCMC_CSCDR2);
+
+		sel = __SHIFTOUT(cscmr1, CSCMR1_CSPI_CLK_SEL);
+		switch (sel) {
+		case 0:
+		case 1:
+		case 2:
+			freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
+			break;
+		case 3:
+			freq = imx51_get_clock(IMX51CLK_LP_APM);
+			break;
+		}
+
+		freq = freq / (1 + __SHIFTOUT(cscdr2, CSCDR2_ECSPI_CLK_PRED)) /
+		    (1 + __SHIFTOUT(cscdr2, CSCDR2_ECSPI_CLK_PODF));
+
+		return freq;
 	default:
 		aprint_error_dev(ccm_softc->sc_dev,
 		    "clock %d: not supported yet\n", clk);

Index: src/sys/arch/arm/imx/imx51_ccmreg.h
diff -u src/sys/arch/arm/imx/imx51_ccmreg.h:1.2 src/sys/arch/arm/imx/imx51_ccmreg.h:1.3
--- src/sys/arch/arm/imx/imx51_ccmreg.h:1.2	Sat Sep  1 00:07:32 2012
+++ src/sys/arch/arm/imx/imx51_ccmreg.h	Sat Mar 22 09:28:08 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: imx51_ccmreg.h,v 1.2 2012/09/01 00:07:32 matt Exp $	*/
+/*	$NetBSD: imx51_ccmreg.h,v 1.3 2014/03/22 09:28:08 hkenken Exp $	*/
 /*
  * Copyright (c) 2011, 2012  Genetec Corporation.  All rights reserved.
  * Written by Hashimoto Kenichi for Genetec Corporation.
@@ -85,6 +85,7 @@
 #define	CCMC_CSCMR1	0x001c
 #define	 CSCMR1_UART_CLK_SEL_SHIFT	24
 #define	 CSCMR1_UART_CLK_SEL_MASK	__BITS(25, CSCMR1_UART_CLK_SEL_SHIFT)
+#define	 CSCMR1_CSPI_CLK_SEL		__BITS(5, 4)
 #define	CCMC_CSCMR2	0x0020
 #define	CCMC_CSCDR1	0x0024
 #define	 CSCDR1_UART_CLK_PRED_SHIFT	3
@@ -96,6 +97,8 @@
 #define	CCMC_CDCDR	0x0030
 #define	CCMC_CHSCCDR	0x0034		// i.MX6
 #define	CCMC_CSCDR2	0x0038
+#define	 CSCDR2_ECSPI_CLK_PRED		__BITS(27, 25)
+#define	 CSCDR2_ECSPI_CLK_PODF		__BITS(24, 19)
 #define	CCMC_CSCDR3	0x003c
 #define	CCMC_CSCDR4	0x0040
 #define	CCMC_CWDR	0x0044

Added files:

Index: src/sys/arch/arm/imx/imx51_spi.c
diff -u /dev/null src/sys/arch/arm/imx/imx51_spi.c:1.1
--- /dev/null	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imx51_spi.c	Sat Mar 22 09:28:08 2014
@@ -0,0 +1,99 @@
+/*	$NetBSD: imx51_spi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+
+/*-
+ * Copyright (c) 2014  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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: imx51_spi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $");
+
+#include "locators.h"
+#include "opt_imx.h"
+#include "opt_imxspi.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imxspivar.h>
+#include <arm/imx/imx51reg.h>
+#include <arm/imx/imx51var.h>
+#include <arm/imx/imx51_ccmvar.h>
+
+struct imx51spi_softc {
+	struct imxspi_softc sc_spi;
+	struct spi_chipset_tag sc_tag;
+};
+
+CFATTACH_DECL_NEW(imx51_spi, sizeof(struct imx51spi_softc),
+    imxspi_match, imxspi_attach, NULL, NULL);
+
+static int
+imxspi_cs_enable(void *arg, int slave)
+{
+	return 0;
+}
+
+static int
+imxspi_cs_disable(void *arg, int slave)
+{
+	return 0;
+}
+
+int
+imxspi_match(device_t parent, cfdata_t cf, void *aux)
+{
+	if (strcmp(cf->cf_name, "imxspi") == 0)
+		return 1;
+
+	return 0;
+}
+
+void
+imxspi_attach(device_t parent, device_t self, void *aux)
+{
+	struct imx51spi_softc *sc = device_private(self);
+	struct axi_attach_args *aa = aux;
+	struct imxspi_attach_args saa;
+	int cf_flags = device_cfdata(self)->cf_flags;
+
+	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_spi.sc_dev = self;
+
+	imxspi_attach_common(parent, &sc->sc_spi, &saa);
+}
Index: src/sys/arch/arm/imx/imxcspireg.h
diff -u /dev/null src/sys/arch/arm/imx/imxcspireg.h:1.1
--- /dev/null	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxcspireg.h	Sat Mar 22 09:28:08 2014
@@ -0,0 +1,93 @@
+/*	$NetBSD: imxcspireg.h,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+
+/*
+ * Copyright (c) 2014  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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+#ifndef	_ARM_IMX_IMXCSPIREG_H_
+#define	_ARM_IMX_IMXCSPIREG_H_
+
+#define	CSPI_RXDATA		0x00
+#define	CSPI_TXDATA		0x04
+#define	CSPI_CONREG		0x08
+#ifdef IMX51
+#define	 CSPI_CON_CS		__BITS(13, 12)
+#define	 CSPI_CON_DRCTL		__BITS( 9,  8)
+#define	 CSPI_CON_BITCOUNT	__BITS(31, 20)
+#else
+#define	 CSPI_CON_CS		__BITS(25, 24)
+#define	 CSPI_CON_DRCTL		__BITS(21, 20)
+#define	 CSPI_CON_BITCOUNT	__BITS(12,  8)
+#endif
+#define	 CSPI_CON_DIV		__BITS(18, 16)
+#define	 CSPI_CON_SSPOL		__BIT(7)	/* SPI SS Polarity Select */
+#define	 CSPI_CON_SSCTL		__BIT(6)	/* In master mode, this bit
+						 * selects the output wave form
+						 * for the SS signal.
+						 */
+#define	 CSPI_CON_PHA		__BIT(5)	/* PHA */
+#define	 CSPI_CON_POL		__BIT(4)	/* POL */
+#define	 CSPI_CON_SMC		__BIT(3)	/* SMC */
+#define	 CSPI_CON_XCH		__BIT(2)	/* XCH */
+#define	 CSPI_CON_MODE		__BIT(1)	/* MODE */
+#define	 CSPI_CON_ENABLE	__BIT(0)	/* EN */
+#define	CSPI_INTREG		0x0c
+#define	 CSPI_INTR_ALL_EN	0x000001ff	/* All Intarruption Enabled */
+#ifdef IMX51
+#define	 CSPI_INTR_TC_EN	__BIT(7)	/* TX Complete */
+#else
+#define	 CSPI_INTR_TC_EN	__BIT(8)	/* TX Complete */
+#define	 CSPI_INTR_BO_EN	__BIT(7)	/* Bit Counter Overflow */
+#endif
+#define	 CSPI_INTR_RO_EN	__BIT(6)	/* RXFIFO Overflow */
+#define	 CSPI_INTR_RF_EN	__BIT(5)	/* RXFIFO Full */
+#define	 CSPI_INTR_RH_EN	__BIT(4)	/* RXFIFO Half Full */
+#define	 CSPI_INTR_RR_EN	__BIT(3)	/* RXFIFO Ready */
+#define	 CSPI_INTR_TF_EN	__BIT(2)	/* TXFIFO Full */
+#define	 CSPI_INTR_TH_EN	__BIT(1)	/* TXFIFO Half Empty */
+#define	 CSPI_INTR_TE_EN	__BIT(0)	/* TXFIFO Empty */
+#define	CSPI_DMAREG		0x10
+#define	CSPI_STATREG		0x14
+#ifdef IMX51
+#define	 CSPI_STAT_CLR_TC	__BIT(7)	/* Clear TC of status register */
+#define  CSPI_STAT_CLR		CSPI_STAT_CLR_TC
+#else
+#define	 CSPI_STAT_CLR_TC	__BIT(8)	/* Clear TC of status register */
+#define	 CSPI_STAT_CLR_BO	__BIT(7)	/* Clear BO of status register */
+#define  CSPI_STAT_CLR		(CSPI_STAT_CLR_TC | CSPI_STAT_CLR_BO)
+#endif
+#define	 CSPI_STAT_RO		__BIT(6)	/* RXFIFO Overflow */
+#define	 CSPI_STAT_RF		__BIT(5)	/* RXFIFO Full */
+#define	 CSPI_STAT_RH		__BIT(4)	/* RXFIFO Half Full */
+#define	 CSPI_STAT_RR		__BIT(3)	/* RXFIFO Ready */
+#define	 CSPI_STAT_TF		__BIT(2)	/* TXFIFO Full */
+#define	 CSPI_STAT_TH		__BIT(1)	/* TXFIFO Half Empty */
+#define	 CSPI_STAT_TE		__BIT(0)	/* TXFIFO Empty */
+#define	CSPI_PERIODREG		0x18
+#define	CSPI_TESTREG		0x1c
+
+#define SPI_SIZE		0x100
+
+#endif	/* _ARM_IMX_IMXCSPIREG_H_ */
Index: src/sys/arch/arm/imx/imxecspireg.h
diff -u /dev/null src/sys/arch/arm/imx/imxecspireg.h:1.1
--- /dev/null	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxecspireg.h	Sat Mar 22 09:28:08 2014
@@ -0,0 +1,80 @@
+/*	$NetBSD: imxecspireg.h,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+
+/*
+ * Copyright (c) 2012  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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+#ifndef	_ARM_IMX_IMXECSPIREG_H_
+#define	_ARM_IMX_IMXECSPIREG_H_
+
+#define	ECSPI_RXDATA		0x00
+#define	ECSPI_TXDATA		0x04
+#define	ECSPI_CONREG		0x08
+#define	 ECSPI_CON_BITCOUNT	__BITS(31, 20)
+#define	 ECSPI_CON_CS		__BITS(19,18)
+#define	 ECSPI_CON_DRCTL	__BITS(17,16)
+#define	 ECSPI_CON_PREDIV	__BITS(15,12)	/* PRE DIVIDER */
+#define	 ECSPI_CON_DIV		__BITS(11, 8)	/* POST DIVIDER */
+#define	 ECSPI_CON_MODE		__BITS( 7, 4)	/* MODE */
+#define	 ECSPI_CON_SMC		__BIT(3)	/* SMC */
+#define	 ECSPI_CON_XCH		__BIT(2)	/* XCH */
+#define	 ECSPI_CON_HW		__BIT(1)	/* HW */
+#define	 ECSPI_CON_ENABLE	__BIT(0)	/* EN */
+#define	ECSPI_CONFIGREG		0x0c
+#define	 ECSPI_CONFIG_HT_LEN	__BITS(28,24)	/* HT LENGHT */
+#define	 ECSPI_CONFIG_SCLK_CTL	__BITS(23,20)	/* SCLK CTL */
+#define	 ECSPI_CONFIG_DATA_CTL	__BITS(19,16)	/* DATA CTL */
+#define	 ECSPI_CONFIG_SSB_POL	__BITS(15,12)	/* SSB POL */
+#define	 ECSPI_CONFIG_SSB_CTL	__BITS(11, 8)	/* SSB CTL */
+#define	 ECSPI_CONFIG_SCLK_POL	__BITS( 7, 4)	/* SCLK POL */
+#define	 ECSPI_CONFIG_SCLK_PHA	__BITS( 3, 0)	/* SCLK PHA */
+#define	ECSPI_INTREG		0x10
+#define	 ECSPI_INTR_ALL_EN	__BITS( 7, 0)	/* All Intarruption Enabled */
+#define	 ECSPI_INTR_TC_EN	__BIT(7)	/* TX Complete */
+#define	 ECSPI_INTR_RO_EN	__BIT(6)	/* RXFIFO Overflow */
+#define	 ECSPI_INTR_RF_EN	__BIT(5)	/* RXFIFO Full */
+#define	 ECSPI_INTR_RD_EN	__BIT(4)	/* RXFIFO Data Request */
+#define	 ECSPI_INTR_RR_EN	__BIT(3)	/* RXFIFO Ready */
+#define	 ECSPI_INTR_TF_EN	__BIT(2)	/* TXFIFO Full */
+#define	 ECSPI_INTR_TD_EN	__BIT(1)	/* TXFIFO Data Request */
+#define	 ECSPI_INTR_TE_EN	__BIT(0)	/* TXFIFO Empty */
+#define	ECSPI_DMAREG		0x14
+#define	ECSPI_STATREG		0x18
+#define	 ECSPI_STAT_CLR_TC	__BIT(7)	/* Clear Transfer Completed */
+#define	 ECSPI_STAT_CLR_RO	__BIT(6)	/* Clear RXFIFO Overflow */
+#define  ECSPI_STAT_CLR		ECSPI_STAT_CLR_TC
+#define  ECSPI_STAT_RF		__BIT(5)
+#define  ECSPI_STAT_RDR		__BIT(4)
+#define  ECSPI_STAT_RR		__BIT(3)
+#define  ECSPI_STAT_TF		__BIT(2)
+#define  ECSPI_STAT_TDR		__BIT(1)
+#define  ECSPI_STAT_TE		__BIT(0)
+#define	ECSPI_PERIODREG		0x1c
+#define	ECSPI_TESTREG		0x20
+#define	ECSPI_MSGDATA		0x40
+
+#define ECSPI_SIZE		0x50
+
+#endif	/* _ARM_IMX_IMXECSPIREG_H_ */
Index: src/sys/arch/arm/imx/imxspi.c
diff -u /dev/null src/sys/arch/arm/imx/imxspi.c:1.1
--- /dev/null	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxspi.c	Sat Mar 22 09:28:08 2014
@@ -0,0 +1,419 @@
+/*	$NetBSD: imxspi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+
+/*-
+ * Copyright (c) 2014  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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+/*
+ * this module support CSPI and eCSPI.
+ * i.MX51 have 2 eCSPI and 1 CSPI modules.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $");
+
+#include "opt_imx.h"
+#include "opt_imxspi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/proc.h>
+#include <sys/intr.h>
+
+#include <sys/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/imx/imxspivar.h>
+#include <arm/imx/imxspireg.h>
+
+/* 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);
+void imxspi_send(struct imxspi_softc *);
+void imxspi_recv(struct imxspi_softc *);
+void imxspi_sched(struct imxspi_softc *);
+
+#define	IMXSPI(x)							      \
+	((sc->sc_enhanced) ? __CONCAT(ECSPI_, x) : __CONCAT(CSPI_, x))
+#define	READ_REG(sc, x)							      \
+	bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXSPI(x))
+#define	WRITE_REG(sc, x, v)						      \
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXSPI(x), (v))
+
+#ifdef IMXSPI_DEBUG
+int imxspi_debug = IMXSPI_DEBUG;
+#define	DPRINTFN(n,x)   if (imxspi_debug>(n)) printf x;
+#else
+#define	DPRINTFN(n,x)
+#endif
+
+int
+imxspi_attach_common(device_t parent, struct imxspi_softc *sc, void *aux)
+{
+	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;
+
+	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;
+	}
+
+	aprint_normal(": i.MX %sCSPI Controller (clock %ld Hz)\n",
+	    ((sc->sc_enhanced) ? "e" : ""), sc->sc_freq);
+
+	/* Initialize SPI controller */
+	sc->sc_spi.sct_cookie = sc;
+	if (sc->sc_enhanced)
+		sc->sc_spi.sct_configure = imxspi_configure_enhanced;
+	else
+		sc->sc_spi.sct_configure = imxspi_configure;
+	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;
+	if (!sc->sc_spi.sct_nslaves)
+		aprint_error_dev(sc->sc_dev, "no slaves!\n");
+
+	sba.sba_controller = &sc->sc_spi;
+
+	/* initialize the queue */
+	SIMPLEQ_INIT(&sc->sc_q);
+
+	/* configure SPI */
+	/* Setup Control Register */
+	WRITE_REG(sc, CONREG, __SHIFTIN(0, IMXSPI(CON_DRCTL)) |
+	    __SHIFTIN(8 - 1, IMXSPI(CON_BITCOUNT)) |
+	    __SHIFTIN(0xf, IMXSPI(CON_MODE)) | IMXSPI(CON_ENABLE));
+
+	/* TC and RR interruption */
+	WRITE_REG(sc, INTREG,  (IMXSPI(INTR_TC_EN) | IMXSPI(INTR_RR_EN)));
+	WRITE_REG(sc, STATREG, IMXSPI(STAT_CLR));
+
+	WRITE_REG(sc, PERIODREG, 0x0);
+
+	/* enable device interrupts */
+	sc->sc_ih = intr_establish(saa->saa_irq, IPL_BIO, IST_LEVEL,
+	    imxspi_intr, sc);
+
+	/* attach slave devices */
+	(void)config_found_ia(sc->sc_dev, "spibus", &sba, spibus_print);
+
+	return 0;
+}
+
+static int
+imxspi_configure(void *arg, int slave, int mode, int speed)
+{
+	struct imxspi_softc *sc = arg;
+	uint32_t div_cnt = 0;
+	uint32_t div;
+	uint32_t contrl = 0;
+
+	div = (sc->sc_freq + (speed - 1)) / speed;
+	div = div - 1;
+	for (div_cnt = 0; div > 0; div_cnt++)
+		div >>= 1;
+
+	div_cnt = div_cnt - 2;
+	if (div_cnt >= 7)
+		div_cnt = 7;
+
+	contrl = READ_REG(sc, CONREG);
+	contrl &= ~CSPI_CON_DIV;
+	contrl |= __SHIFTIN(div_cnt, CSPI_CON_DIV);
+
+	contrl &= ~(CSPI_CON_POL | CSPI_CON_PHA);
+	switch (mode) {
+	case SPI_MODE_0:
+		/* CPHA = 0, CPOL = 0 */
+		break;
+	case SPI_MODE_1:
+		/* CPHA = 1, CPOL = 0 */
+		contrl |= CSPI_CON_PHA;
+		break;
+	case SPI_MODE_2:
+		/* CPHA = 0, CPOL = 1 */
+		contrl |= CSPI_CON_POL;
+		break;
+	case SPI_MODE_3:
+		/* CPHA = 1, CPOL = 1 */
+		contrl |= CSPI_CON_POL;
+		contrl |= CSPI_CON_PHA;
+		break;
+	default:
+		return EINVAL;
+	}
+	WRITE_REG(sc, CONREG, contrl);
+
+	DPRINTFN(3, ("%s: slave %d mode %d speed %d\n",
+		__func__, slave, mode, speed));
+
+	return 0;
+}
+
+static int
+imxspi_configure_enhanced(void *arg, int slave, int mode, int speed)
+{
+	struct imxspi_softc *sc = arg;
+	uint32_t div_cnt = 0;
+	uint32_t div;
+	uint32_t contrl = 0;
+	uint32_t config = 0;
+
+	div = (sc->sc_freq + (speed - 1)) / speed;
+	for (div_cnt = 0; div > 0; div_cnt++)
+		div >>= 1;
+
+	if (div_cnt >= 15)
+		div_cnt = 15;
+
+	contrl = READ_REG(sc, CONREG);
+	contrl |= __SHIFTIN(div_cnt, ECSPI_CON_DIV);
+	contrl |= __SHIFTIN(slave, ECSPI_CON_CS);
+	contrl |= __SHIFTIN(__BIT(slave), ECSPI_CON_MODE);
+	WRITE_REG(sc, CONREG, contrl);
+
+	config = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ECSPI_CONFIGREG);
+	config &= ~(__SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL) |
+	    __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA));
+	switch (mode) {
+	case SPI_MODE_0:
+		/* CPHA = 0, CPOL = 0 */
+		break;
+	case SPI_MODE_1:
+		/* CPHA = 1, CPOL = 0 */
+		config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA);
+		break;
+	case SPI_MODE_2:
+		/* CPHA = 0, CPOL = 1 */
+		config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL);
+		break;
+	case SPI_MODE_3:
+		/* CPHA = 1, CPOL = 1 */
+		config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_PHA);
+		config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SCLK_POL);
+		break;
+	default:
+		return EINVAL;
+	}
+	config |= __SHIFTIN(__BIT(slave), ECSPI_CONFIG_SSB_CTL);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, ECSPI_CONFIGREG, config);
+
+	DPRINTFN(3, ("%s: slave %d mode %d speed %d\n",
+		__func__, slave, mode, speed));
+
+	return 0;
+}
+
+void
+imxspi_send(struct imxspi_softc *sc)
+{
+	uint32_t data;
+	struct spi_chunk *chunk;
+
+	/* fill the fifo */
+	while ((chunk = sc->sc_wchunk) != NULL) {
+		while (chunk->chunk_wresid) {
+			/* transmit fifo full? */
+			if (READ_REG(sc, STATREG) & IMXSPI(STAT_TF))
+				return;
+
+			if (chunk->chunk_wptr) {
+				data = *chunk->chunk_wptr;
+				chunk->chunk_wptr++;
+			} else {
+				data = 0xff;
+			}
+			chunk->chunk_wresid--;
+
+			WRITE_REG(sc, TXDATA, data);
+		}
+		/* advance to next transfer */
+		sc->sc_wchunk = sc->sc_wchunk->chunk_next;
+	}
+
+	if (!(READ_REG(sc, STATREG) & IMXSPI(INTR_TE_EN)))
+		WRITE_REG(sc, CONREG, READ_REG(sc, CONREG) | IMXSPI(CON_XCH));
+}
+
+void
+imxspi_recv(struct imxspi_softc *sc)
+{
+	uint32_t		data;
+	struct spi_chunk	*chunk;
+
+	while ((chunk = sc->sc_rchunk) != NULL) {
+		while (chunk->chunk_rresid) {
+			/* rx fifo empty? */
+			if ((!(READ_REG(sc, STATREG) & IMXSPI(STAT_RR))))
+				return;
+
+			/* collect rx data */
+			data = READ_REG(sc, RXDATA);
+			if (chunk->chunk_rptr) {
+				*chunk->chunk_rptr = data & 0xff;
+				chunk->chunk_rptr++;
+			}
+
+			chunk->chunk_rresid--;
+		}
+		/* advance next to next transfer */
+		sc->sc_rchunk = sc->sc_rchunk->chunk_next;
+	}
+}
+
+
+void
+imxspi_sched(struct imxspi_softc *sc)
+{
+	struct spi_transfer *st;
+	uint32_t chipselect;
+
+	while ((st = spi_transq_first(&sc->sc_q)) != NULL) {
+		/* remove the item */
+		spi_transq_dequeue(&sc->sc_q);
+
+		/* note that we are working on it */
+		sc->sc_transfer = st;
+
+		/* chip slect */
+		if (sc->sc_tag->spi_cs_enable != NULL)
+			sc->sc_tag->spi_cs_enable(sc->sc_tag->cookie,
+			    st->st_slave);
+
+		/*chip slect*/
+		chipselect = READ_REG(sc, CONREG);
+		chipselect &= ~IMXSPI(CON_CS);
+		chipselect |= __SHIFTIN(st->st_slave, IMXSPI(CON_CS));
+		WRITE_REG(sc, CONREG, chipselect);
+
+		delay(1);
+
+		/* setup chunks */
+		sc->sc_rchunk = sc->sc_wchunk = st->st_chunks;
+
+		/* now kick the master start to get the chip running */
+		imxspi_send(sc);
+
+		sc->sc_running = TRUE;
+		return;
+	}
+
+	DPRINTFN(2, ("%s: nothing to do anymore\n", __func__));
+	sc->sc_running = FALSE;
+}
+
+void
+imxspi_done(struct imxspi_softc *sc, int err)
+{
+	struct spi_transfer *st;
+
+	/* called from interrupt handler */
+	if ((st = sc->sc_transfer) != NULL) {
+		if (sc->sc_tag->spi_cs_disable != NULL)
+			sc->sc_tag->spi_cs_disable(sc->sc_tag->cookie,
+			    st->st_slave);
+
+		sc->sc_transfer = NULL;
+		spi_done(st, err);
+	}
+	/* make sure we clear these bits out */
+	sc->sc_wchunk = sc->sc_rchunk = NULL;
+	imxspi_sched(sc);
+}
+
+static int
+imxspi_intr(void *arg)
+{
+	struct imxspi_softc *sc = arg;
+	uint32_t intr, sr;
+	int err = 0;
+
+	if ((intr = READ_REG(sc, INTREG)) == 0) {
+		/* interrupts are not enabled, get out */
+		DPRINTFN(4, ("%s: interrupts are not enabled\n", __func__));
+		return 0;
+	}
+
+	sr = READ_REG(sc, STATREG);
+	if (!(sr & intr)) {
+		/* interrupt did not happen, get out */
+		DPRINTFN(3, ("%s: interrupts did not happen\n", __func__));
+		return 0;
+	}
+
+	/* Transfer Conplete? */
+	if (sr & IMXSPI(INTR_TC_EN)) {
+		/* complete TX */
+		imxspi_send(sc);
+	}
+
+	/* RXFIFO ready */
+	if (sr & IMXSPI(INTR_RR_EN)) {
+		imxspi_recv(sc);
+		if(sc->sc_wchunk == NULL &&sc->sc_rchunk == NULL)
+			imxspi_done(sc, err);
+	}
+
+	/* status register clear */
+	WRITE_REG(sc, STATREG, sr);
+
+	return 1;
+}
+
+int
+imxspi_transfer(void *arg, struct spi_transfer *st)
+{
+	struct imxspi_softc *sc = arg;
+	int s;
+
+	/* make sure we select the right chip */
+	s = splserial();
+	spi_transq_enqueue(&sc->sc_q, st);
+	if (sc->sc_running == FALSE)
+		imxspi_sched(sc);
+	splx(s);
+
+	return 0;
+}
+
Index: src/sys/arch/arm/imx/imxspireg.h
diff -u /dev/null src/sys/arch/arm/imx/imxspireg.h:1.1
--- /dev/null	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxspireg.h	Sat Mar 22 09:28:08 2014
@@ -0,0 +1,37 @@
+/*	$NetBSD: imxspireg.h,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+
+/*
+ * Copyright (c) 2014  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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+#ifndef	_ARM_IMX_IMXSPIREG_H_
+#define	_ARM_IMX_IMXSPIREG_H_
+
+#include <arm/imx/imxcspireg.h>
+#include <arm/imx/imxecspireg.h>
+
+#define SPI_SIZE	0x100
+
+#endif	/* _ARM_IMX_IMXSPIREG_H_ */
Index: src/sys/arch/arm/imx/imxspivar.h
diff -u /dev/null src/sys/arch/arm/imx/imxspivar.h:1.1
--- /dev/null	Sat Mar 22 09:28:08 2014
+++ src/sys/arch/arm/imx/imxspivar.h	Sat Mar 22 09:28:08 2014
@@ -0,0 +1,80 @@
+/*	$NetBSD: imxspivar.h,v 1.1 2014/03/22 09:28:08 hkenken Exp $	*/
+
+/*
+ * Copyright (c) 2014  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 GENETEC CORPORATION ``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 GENETEC CORPORATION
+ * 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.
+ */
+
+#ifndef	_ARM_IMX_IMXSPIVAR_H_
+#define	_ARM_IMX_IMXSPIVAR_H_
+
+#include <dev/spi/spivar.h>
+
+typedef struct spi_chipset_tag {
+	void *cookie;
+
+	int (*spi_cs_enable)(void *, int);
+	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;
+	bus_space_tag_t  sc_iot;
+	bus_space_handle_t sc_ioh;
+	spi_chipset_tag_t sc_tag;
+
+	struct spi_controller sc_spi;
+	unsigned long sc_freq;
+	struct spi_chunk *sc_wchunk;
+	struct spi_chunk *sc_rchunk;
+	void *sc_ih;
+	struct spi_transfer *sc_transfer;
+	bool  sc_running;
+	SIMPLEQ_HEAD(,spi_transfer) sc_q;
+
+	int sc_enhanced;
+};
+
+int imxspi_attach_common(device_t, struct imxspi_softc *, void *);
+
+/*
+ * defined in machine dependent code
+ */
+int imxspi_match(device_t, cfdata_t, void *);
+void imxspi_attach(device_t, device_t, void *);
+
+#endif	/* _ARM_IMX_IMXSPIVAR_H_ */

Reply via email to