Module Name: src
Committed By: bsh
Date: Tue Nov 30 13:05:27 UTC 2010
Modified Files:
src/sys/arch/arm/imx: files.imx51 imx51_axi.c imx51reg.h imx51var.h
imxgpioreg.h imxkppreg.h
Added Files:
src/sys/arch/arm/imx: imx51_gpio.c imx51_iomux.c imx51_usb.c imxgpio.c
imxgpiovar.h imxusb.c imxusbreg.h imxusbvar.h
Log Message:
Support GPIO, IOMUX, and USB on i.MX51.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/imx/files.imx51 \
src/sys/arch/arm/imx/imx51_axi.c src/sys/arch/arm/imx/imx51reg.h \
src/sys/arch/arm/imx/imx51var.h src/sys/arch/arm/imx/imxgpioreg.h \
src/sys/arch/arm/imx/imxkppreg.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/imx51_gpio.c \
src/sys/arch/arm/imx/imx51_iomux.c src/sys/arch/arm/imx/imx51_usb.c \
src/sys/arch/arm/imx/imxgpio.c src/sys/arch/arm/imx/imxgpiovar.h \
src/sys/arch/arm/imx/imxusb.c src/sys/arch/arm/imx/imxusbreg.h \
src/sys/arch/arm/imx/imxusbvar.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.1 src/sys/arch/arm/imx/files.imx51:1.2
--- src/sys/arch/arm/imx/files.imx51:1.1 Sat Nov 13 07:11:02 2010
+++ src/sys/arch/arm/imx/files.imx51 Tue Nov 30 13:05:27 2010
@@ -1,4 +1,4 @@
-# $NetBSD: files.imx51,v 1.1 2010/11/13 07:11:02 bsh Exp $
+# $NetBSD: files.imx51,v 1.2 2010/11/30 13:05:27 bsh Exp $
#
# Configuration info for the Freescale i.MX51
#
@@ -46,14 +46,15 @@
defparam opt_imx51clk.h IMX51_IPGCLK_FREQ
# iMX GPIO
-# device imxgpio: gpiobus
-# attach imxgpio at ahb
-# file arch/arm/imx/imx31_gpio.c imxgpio needs-flag
+device imxgpio: gpiobus
+attach imxgpio at axi
+file arch/arm/imx/imxgpio.c imxgpio needs-flag
+file arch/arm/imx/imx51_gpio.c imxgpio
# iMX IOMUX
device imxiomux : bus_space_generic
attach imxiomux at axi
-file arch/arm/imx/imx31_iomux.c imxiomux
+file arch/arm/imx/imx51_iomux.c imxiomux
# LCD controller
# device lcd : bus_dma_generic, wsemuldisplaydev, rasops16, rasops8, rasops4, rasops_rotation
@@ -73,8 +74,13 @@
file arch/arm/imx/imx51_uart.c imxuart
defflag opt_imxuart.h IMXUARTCONSOLE
-# attach ohci at ahb with ohci_ahb : bus_dma_generic
-# file arch/arm/imx/ochi_axi.c ohci_axi
+# USB controller
+# attach of this driver need to be specified in paltform configuration
+device imxusbc { unit, irq } : bus_dma_generic
+file arch/arm/imx/imx51_usb.c imxusbc
+
+attach ehci at imxusbc with imxehci
+file arch/arm/imx/imxusb.c imxehci
# attach wdc at ahb with wdc_ahb : bus_dma_generic
# file arch/arm/imx/wdc_axi.c wdc_axi
Index: src/sys/arch/arm/imx/imx51_axi.c
diff -u src/sys/arch/arm/imx/imx51_axi.c:1.1 src/sys/arch/arm/imx/imx51_axi.c:1.2
--- src/sys/arch/arm/imx/imx51_axi.c:1.1 Sat Nov 13 07:11:02 2010
+++ src/sys/arch/arm/imx/imx51_axi.c Tue Nov 30 13:05:27 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: imx51_axi.c,v 1.1 2010/11/13 07:11:02 bsh Exp $ */
+/* $NetBSD: imx51_axi.c,v 1.2 2010/11/30 13:05:27 bsh Exp $ */
/*-
* Copyright (c) 2010 SHIMIZU Ryo <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx51_axi.c,v 1.1 2010/11/13 07:11:02 bsh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx51_axi.c,v 1.2 2010/11/30 13:05:27 bsh Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -101,9 +101,11 @@
aa = aux;
if ((strcmp(cf->cf_name, "tzic") != 0) &&
- (strcmp(cf->cf_name, "imxuart") != 0))
+ (strcmp(cf->cf_name, "imxuart") != 0) &&
+ (strcmp(cf->cf_name, "imxgpio") != 0))
return 0;
+ aa->aa_name = cf->cf_name;
aa->aa_addr = cf->cf_loc[AXICF_ADDR];
aa->aa_size = cf->cf_loc[AXICF_SIZE];
aa->aa_irq = cf->cf_loc[AXICF_IRQ];
Index: src/sys/arch/arm/imx/imx51reg.h
diff -u src/sys/arch/arm/imx/imx51reg.h:1.1 src/sys/arch/arm/imx/imx51reg.h:1.2
--- src/sys/arch/arm/imx/imx51reg.h:1.1 Sat Nov 13 07:11:03 2010
+++ src/sys/arch/arm/imx/imx51reg.h Tue Nov 30 13:05:27 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: imx51reg.h,v 1.1 2010/11/13 07:11:03 bsh Exp $ */
+/* $NetBSD: imx51reg.h,v 1.2 2010/11/30 13:05:27 bsh Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -89,12 +89,72 @@
#define USBOH3_BASE 0x73f80000
#define USBOH3_PL301_BASE 0x73fc4000
-#define USB_OTG_BASE 0x43F88000
-#define USB_EHCI1_BASE 0x43F88200
-#define USB_EHCI2_BASE 0x43F88400
-#define USB_EHCI_SIZE 0x0200
-#define USB_CONTROL 0x43F88600
+#define USBOH3_EHCI_SIZE 0x200
+#define USBOH3_OTG 0x000
+#define USBOH3_EHCI(n) (USBOH3_EHCI_SIZE*(n)) /* n=1,2,3 */
+
+/* USB_CTRL register */
+#define USBOH3_USBCTRL 0x800
+#define USBCTRL_OWIR __BIT(31) /* OTG Wakeup interrupt request */
+#define USBCTRL_OSIC_SHIFT 29
+#define USBCTRL_OSIC __BITS(29,30) /* OTG Serial interface configuration */
+#define USBCTRL_OUIE __BIT(28) /* OTG Wake-up interrupt enable */
+#define USBCTRL_OBPAL __BITS(25,26) /* OTG Bypass value */
+#define USBCTRL_OPM __BIT(24) /* OTG Power Mask */
+#define USBCTRL_ICVOL __BIT(23) /* Host1 IC_USB voltage status */
+#define USBCTRL_ICTPIE __BIT(19) /* IC USB TP interrupt enable */
+#define USBCTRL_UBPCKE __BIT(18) /* Bypass clock enable */
+#define USBCTRL_H1TCKOEN __BIT(17) /* Host1 ULPO PHY clock enable */
+#define USBCTRL_ICTPC __BIT(16) /* Clear IC TP interrupt flag */
+#define USBCTRL_H1WIR __BIT(15) /* Host1 wakeup interrupt request */
+#define USBCTRL_H1STC_SHIFT 13
+#define USBCTRL_H1SIC __BITS(13,14) /* Host1 serial interface config */
+#define USBCTRL_H1UIE __BIT(12) /* Host1 ILPI interrupt enable */
+#define USBCTRL_H1WIE __BIT(11) /* Host1 wakeup interrupt enable */
+#define USBCTRL_H1BPVAL __BITS(9,10) /* Host1 bypass value */
+#define USBCTRL_H1PM __BIT(8) /* Host1 power mask */
+#define USBCTRL_OHSTLL __BIT(7) /* OTG ULPI TLL enable */
+#define USBCTRL_H1HSTLL __BIT(6) /* Host1 ULPI TLL enable */
+#define USBCTRL_H1DISFSTTL __BIT(4) /* Host1 serial TLL disable */
+#define USBCTRL_OTCKOEN __BIT(1) /* OTG ULPI PHY clock enable */
+#define USBCTRL_BPE __BIT(0) /* Bypass enable */
+
+#define USBOH3_OTGMIRROR 0x804
+#define USBOH3_PHYCTRL0 0x808
+#define PHYCTRL0_VLOAD __BIT(31)
+#define PHYCTRL0_VCONTROL __BITS(27,30)
+#define PHYCTRL0_CONF2 __BIT(26)
+#define PHYCTRL0_CONF3 __BIT(25)
+#define PHYCTRL0_CHGRDETEN __BIT(24)
+#define PHYCTRL0_CHGRDETON __BIT(23)
+#define PHYCTRL0_VSTATUS __BITS(15,22)
+#define PHYCTRL0_SUSPENDM __BIT(12)
+#define PHYCTRL0_RESET __BIT(11)
+#define PHYCTRL0_UTMI_ON_CLOCK __BIT(10)
+#define PHYCTRL0_OTG_OVER_CUR_POL __BIT(9)
+#define PHYCTRL0_OTG_OVER_CUR_DIS __BIT(8)
+#define PHYCTRL0_OTG_XCVR_CLK_SEL __BIT(7)
+#define PHYCTRL0_H1_XCVR_CLK_SEL __BIT(4)
+#define PHYCTRL0_PWR_POL __BIT(3)
+#define PHYCTRL0_CHRGDET __BIT(2)
+#define PHYCTRL0_CHRGDET_INT_EN __BIT(1)
+#define PHYCTRL0_CHRGDET_INT_FLG __BIT(0)
+
+#define USBOH3_PHYCTRL1 0x80c
+#define PHYCTRL1_PLLDIVVALUE_MASK __BITS(0,1)
+#define PHYCTRL1_PLLDIVVALUE_19MHZ 0 /* 19.2MHz */
+#define PHYCTRL1_PLLDIVVALUE_24MHZ 1
+#define PHYCTRL1_PLLDIVVALUE_26MHZ 2
+#define PHYCTRL1_PLLDIVVALUE_27MHZ 3
+#define USBOH3_USBCTRL1 0x810
+#define USBCTRL1_UH3_EXT_CLK_EN __BIT(27)
+#define USBCTRL1_UH2_EXT_CLK_EN __BIT(26)
+#define USBCTRL1_UH1_EXT_CLK_EN __BIT(25)
+#define USBCTRL1_OTG_EXT_CLK_EN __BIT(24)
+#define USBOH3_USBCTRL2 0x814
+#define USBOH3_USBCTRL3 0x818
+#define USBOH3_SIZE 0x820
/* GPIO module */
@@ -105,15 +165,14 @@
#define GPIO3_BASE GPIO_BASE(3)
#define GPIO4_BASE GPIO_BASE(4)
-#define GPIO_NPINS 32
-#define GPIO_NGROUPS 3
+#define GPIO_NGROUPS 4
#define KPP_BASE 0x73f94000
/* register definitions in imxkppreg.h */
#define WDOG1_BASE 0x73f98000
#define WDOG2_BASE 0x73f9c000
-#define WDOG_SIZE 0x4000
+#define WDOG_SIZE 0x000a
#define GPT_BASE 0x73fa0000
#define GPT_SIZE 0x4000
@@ -134,25 +193,24 @@
#define IOMUX_CONFIG_ALT5 (5)
#define IOMUX_CONFIG_ALT6 (6)
#define IOMUX_CONFIG_ALT7 (7)
+#define IOMUX_CONFIG_SION __BIT(4)
#define IOMUXC_PAD_CTL 0x03f0 /* pad control */
-#define PAD_CTL_HYS_NONE (0x0 << 8)
-#define PAD_CTL_HYS_ENABLE (0x1 << 8)
-#define PAD_CTL_PKE_NONE (0x0 << 7)
-#define PAD_CTL_PKE_ENABLE (0x1 << 7)
-#define PAD_CTL_PUE_KEEPER (0x0 << 6)
-#define PAD_CTL_PUE_PULL (0x1 << 6)
+#define PAD_CTL_DDR_INPUT __BIT(9)
+#define PAD_CTL_HYS __BIT(8)
+#define PAD_CTL_PKE __BIT(7)
+#define PAD_CTL_PUE __BIT(6)
+#define PAD_CTL_PULL (PAD_CTL_PKE|PAD_CTL_PUE)
+#define PAD_CTL_KEEPER (PAD_CTL_PKE|0)
#define PAD_CTL_PUS_100K_PD (0x0 << 4)
#define PAD_CTL_PUS_47K_PU (0x1 << 4)
#define PAD_CTL_PUS_100K_PU (0x2 << 4)
#define PAD_CTL_PUS_22K_PU (0x3 << 4)
-#define PAD_CTL_ODE_CMOS (0x0 << 3)
-#define PAD_CTL_ODE_OpenDrain (0x1 << 3)
+#define PAD_CTL_ODE __BIT(3) /* opendrain */
#define PAD_CTL_DSE_LOW (0x0 << 1)
#define PAD_CTL_DSE_MID (0x1 << 1)
#define PAD_CTL_DSE_HIGH (0x2 << 1)
#define PAD_CTL_DSE_MAX (0x3 << 1)
-#define PAD_CTL_SRE_SLOW (0x0 << 0)
-#define PAD_CTL_SRE_FAST (0x1 << 0)
+#define PAD_CTL_SRE __BIT(0)
#define IOMUXC_INPUT_CTL 0x08c4 /* input control */
#define INPUT_DAISY_0 0
#define INPUT_DAISY_1 1
@@ -187,7 +245,7 @@
#define SRC_SIZE 0x4000
#define CCM_BASE 0x73fd4000
-#define CCM_SIZE 0x4000
+#define CCM_SIZE 0x0088
#define GPC_BASE 0x73fd8000
#define GPC_SIZE 0x4000
Index: src/sys/arch/arm/imx/imx51var.h
diff -u src/sys/arch/arm/imx/imx51var.h:1.1 src/sys/arch/arm/imx/imx51var.h:1.2
--- src/sys/arch/arm/imx/imx51var.h:1.1 Sat Nov 13 07:11:03 2010
+++ src/sys/arch/arm/imx/imx51var.h Tue Nov 30 13:05:27 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: imx51var.h,v 1.1 2010/11/13 07:11:03 bsh Exp $ */
+/* $NetBSD: imx51var.h,v 1.2 2010/11/30 13:05:27 bsh Exp $ */
#ifndef _ARM_IMX_IMX51VAR_H
#define _ARM_IMX_IMX51VAR_H
@@ -20,4 +20,18 @@
int aa_irqbase;
};
+
+/* iomux utility functions */
+struct iomux_conf {
+ u_int pin;
+#define IOMUX_CONF_EOT ((u_int)(-1))
+ u_short mux;
+ u_short pad;
+};
+
+void iomux_set_function(u_int, u_int);
+void iomux_set_pad(u_int, u_int);
+//void iomux_set_input(u_int, u_int);
+void iomux_mux_config(const struct iomux_conf *);
+
#endif /* _ARM_IMX_IMX51VAR_H */
Index: src/sys/arch/arm/imx/imxgpioreg.h
diff -u src/sys/arch/arm/imx/imxgpioreg.h:1.1 src/sys/arch/arm/imx/imxgpioreg.h:1.2
--- src/sys/arch/arm/imx/imxgpioreg.h:1.1 Sat Nov 13 06:44:11 2010
+++ src/sys/arch/arm/imx/imxgpioreg.h Tue Nov 30 13:05:27 2010
@@ -45,11 +45,6 @@
#define GPIO_ICR_EDGE_RISING 2
#define GPIO_ICR_EDGE_FALLING 3
-#define GPIO_MODULE(pin) ((pin) / GPIO_NPINS)
-
-/*
- * GPIO number
- */
-#define GPIO_NO(group, pin) (((group) - 1) * GPIO_NPINS + (pin))
+#define GPIO_NPINS 32
#endif /* _ARM_IMX_IMXGPIOREG_H */
Index: src/sys/arch/arm/imx/imxkppreg.h
diff -u src/sys/arch/arm/imx/imxkppreg.h:1.1 src/sys/arch/arm/imx/imxkppreg.h:1.2
--- src/sys/arch/arm/imx/imxkppreg.h:1.1 Sat Nov 13 07:11:03 2010
+++ src/sys/arch/arm/imx/imxkppreg.h Tue Nov 30 13:05:27 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: imxkppreg.h,v 1.1 2010/11/13 07:11:03 bsh Exp $ */
+/* $NetBSD: imxkppreg.h,v 1.2 2010/11/30 13:05:27 bsh Exp $ */
/*
* Copyright (c) 2010 Genetec Corporation. All rights reserved.
@@ -50,4 +50,6 @@
#define KPP_KPDR 0x0006 /* data register */
+#define KPP_SIZE 0x0008
+
#endif /* _ARM_IMX_IMXKPPREG_H */
Added files:
Index: src/sys/arch/arm/imx/imx51_gpio.c
diff -u /dev/null src/sys/arch/arm/imx/imx51_gpio.c:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imx51_gpio.c Tue Nov 30 13:05:27 2010
@@ -0,0 +1,114 @@
+/* $NetBSD: imx51_gpio.c,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+
+/* derived from imx31_gpio.c */
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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_gpio.c,v 1.1 2010/11/30 13:05:27 bsh Exp $");
+
+#include "locators.h"
+#include "gpio.h"
+
+#include <sys/param.h>
+#include <sys/evcnt.h>
+#include <sys/atomic.h>
+
+#include <machine/intr.h>
+
+#include <arm/cpu.h>
+#include <arm/armreg.h>
+#include <arm/cpufunc.h>
+
+#include <machine/bus.h>
+
+#include <arm/imx/imx51reg.h>
+#include <arm/imx/imx51var.h>
+#include <arm/pic/picvar.h>
+
+#include <arm/imx/imxgpioreg.h>
+#include <arm/imx/imxgpiovar.h>
+
+#if NGPIO > 0
+#include <sys/gpio.h>
+#include <dev/gpio/gpiovar.h>
+#endif
+
+const int imxgpio_ngroups = GPIO_NGROUPS;
+
+int
+imxgpio_match(device_t parent, cfdata_t cfdata, void *aux)
+{
+ struct axi_attach_args *aa = aux;
+
+ switch(aa->aa_addr) {
+ case GPIO1_BASE:
+ case GPIO2_BASE:
+ case GPIO3_BASE:
+ case GPIO4_BASE:
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+imxgpio_attach(device_t parent, device_t self, void *aux)
+{
+ struct axi_attach_args * const aa = aux;
+ bus_space_handle_t ioh;
+ int error;
+
+ if (aa->aa_irq == AXICF_IRQ_DEFAULT &&
+ aa->aa_irqbase != AXICF_IRQBASE_DEFAULT) {
+ aprint_error_dev(self, "missing intr in config\n");
+ return;
+ }
+ if (aa->aa_irq != AXICF_IRQ_DEFAULT &&
+ aa->aa_irqbase == AXICF_IRQBASE_DEFAULT) {
+ aprint_error_dev(self, "missing irqbase in config\n");
+ return;
+ }
+
+ if (aa->aa_size == AXICF_SIZE_DEFAULT)
+ aa->aa_size = GPIO_SIZE;
+
+ error = bus_space_map(aa->aa_iot, aa->aa_addr, aa->aa_size,
+ 0, &ioh);
+
+ if (error) {
+ aprint_error(": failed to map register %...@%#lx: %d\n",
+ aa->aa_size, aa->aa_addr, error);
+ return;
+ }
+
+ imxgpio_attach_common(self, aa->aa_iot, ioh,
+ (aa->aa_addr - GPIO1_BASE) / 0x4000,
+ aa->aa_irq, aa->aa_irqbase);
+}
+
Index: src/sys/arch/arm/imx/imx51_iomux.c
diff -u /dev/null src/sys/arch/arm/imx/imx51_iomux.c:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imx51_iomux.c Tue Nov 30 13:05:27 2010
@@ -0,0 +1,180 @@
+/* $NetBSD: imx51_iomux.c,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010 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.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx51_iomux.c,v 1.1 2010/11/30 13:05:27 bsh Exp $");
+
+#define _INTR_PRIVATE
+
+#include "locators.h"
+
+#include <sys/param.h>
+#include <sys/evcnt.h>
+#include <sys/atomic.h>
+#include <sys/device.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/intr.h>
+
+#include <arm/cpu.h>
+#include <arm/armreg.h>
+#include <arm/cpufunc.h>
+
+#include <machine/bus.h>
+
+#include <arm/imx/imx51reg.h>
+#include <arm/imx/imx51var.h>
+
+struct iomux_softc {
+ struct device iomux_dev;
+ bus_space_tag_t iomux_memt;
+ bus_space_handle_t iomux_memh;
+};
+
+extern struct cfdriver imxiomux_cd;
+
+#define IOMUX_READ(iomux, reg) \
+ bus_space_read_4((iomux)->iomux_memt, (iomux)->iomux_memh, (reg))
+#define IOMUX_WRITE(iomux, reg, val) \
+ bus_space_write_4((iomux)->iomux_memt, (iomux)->iomux_memh, (reg), (val))
+
+static int iomux_match(device_t, cfdata_t, void *);
+static void iomux_attach(device_t, device_t, void *);
+
+static struct iomux_softc *iomuxsc = NULL;
+
+CFATTACH_DECL(imxiomux,
+ sizeof(struct iomux_softc),
+ iomux_match, iomux_attach,
+ NULL, NULL);
+
+int
+iomux_match(device_t parent, cfdata_t cfdata, void *aux)
+{
+ struct axi_attach_args *axia = aux;
+
+ if (axia->aa_addr != IOMUXC_BASE)
+ return 0;
+
+ return 1;
+}
+
+void
+iomux_attach(device_t parent, device_t self, void *aux)
+{
+ struct axi_attach_args * const axia = aux;
+ struct iomux_softc * const iomux = device_private(self);
+ int error;
+
+ if (axia->aa_size == AXICF_SIZE_DEFAULT)
+ axia->aa_size = IOMUXC_SIZE;
+
+ iomux->iomux_memt = axia->aa_iot;
+ error = bus_space_map(axia->aa_iot, axia->aa_addr, axia->aa_size,
+ 0, &iomux->iomux_memh);
+
+ if (error) {
+ aprint_error(": failed to map register %...@%#lx: %d\n",
+ axia->aa_size, axia->aa_addr, error);
+ return;
+ }
+
+ aprint_normal("\n");
+
+ iomuxsc = iomux;
+}
+
+static void
+iomux_set_function_sub(struct iomux_softc *sc, uint32_t pin, uint32_t fn)
+{
+ bus_size_t mux_ctl_reg = IOMUX_PIN_TO_MUX_ADDRESS(pin);
+
+ if (mux_ctl_reg != IOMUX_MUX_NONE)
+ bus_space_write_4(sc->iomux_memt, sc->iomux_memh,
+ mux_ctl_reg, fn);
+}
+
+void
+iomux_set_function(unsigned int pin, unsigned int fn)
+{
+ iomux_set_function_sub(iomuxsc, pin, fn);
+}
+
+
+static void
+iomux_set_pad_sub(struct iomux_softc *sc, uint32_t pin, uint32_t config)
+{
+ bus_size_t pad_ctl_reg = IOMUX_PIN_TO_PAD_ADDRESS(pin);
+
+ if (pad_ctl_reg != IOMUX_PAD_NONE)
+ bus_space_write_4(sc->iomux_memt, sc->iomux_memh,
+ pad_ctl_reg, config);
+}
+
+void
+iomux_set_pad(unsigned int pin, unsigned int config)
+{
+ iomux_set_pad_sub(iomuxsc, pin, config);
+}
+
+#if 0
+void
+iomux_set_input(unsigned int input, unsigned int config)
+{
+ bus_size_t input_ctl_reg = input;
+
+ bus_space_write_4(iomuxsc->iomux_memt, iomuxsc->iomux_memh,
+ input_ctl_reg, config);
+}
+#endif
+
+void
+iomux_mux_config(const struct iomux_conf *conflist)
+{
+ int i;
+
+ for (i = 0; conflist[i].pin != IOMUX_CONF_EOT; i++) {
+ iomux_set_pad_sub(iomuxsc, conflist[i].pin, conflist[i].pad);
+ iomux_set_function_sub(iomuxsc, conflist[i].pin,
+ conflist[i].mux);
+ }
+}
+
+#if 0
+void
+iomux_input_config(const struct iomux_input_conf *conflist)
+{
+ int i;
+
+ for (i = 0; conflist[i].inout != -1; i++) {
+ iomux_set_inout(iomuxsc, conflist[i].inout,
+ conflist[i].inout_mode);
+ }
+}
+#endif
+
Index: src/sys/arch/arm/imx/imx51_usb.c
diff -u /dev/null src/sys/arch/arm/imx/imx51_usb.c:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imx51_usb.c Tue Nov 30 13:05:27 2010
@@ -0,0 +1,89 @@
+/* $NetBSD: imx51_usb.c,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+/*
+ * Copyright (c) 2010 Genetec Corporation. All rights reserved.
+ * Written by Hiroyuki Bessho 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.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx51_usb.c,v 1.1 2010/11/30 13:05:27 bsh Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/bus.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
+
+#include <arm/imx/imx51reg.h>
+#include <arm/imx/imx51var.h>
+#include <arm/imx/imxusbvar.h>
+#include "locators.h"
+
+static int imxusbc_search(device_t, cfdata_t, const int *, void *);
+
+
+int
+imxusbc_attach_common(device_t parent, device_t self, bus_space_tag_t iot)
+{
+ struct imxusbc_softc *sc = device_private(self);
+
+ sc->sc_iot = iot;
+
+ /* Map entire USBOH3 registers. Host controller drivers
+ * re-use subregions of this. */
+ if (bus_space_map(iot, USBOH3_BASE, USBOH3_SIZE, 0, &sc->sc_ioh))
+ return -1;
+
+ /* attach OTG/EHCI host controllers */
+ config_search_ia(imxusbc_search, self, "imxusbc", NULL);
+
+ return 0;
+}
+
+static int
+imxusbc_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
+{
+ struct imxusbc_softc *sc = device_private(parent);
+ struct imxusbc_attach_args aa;
+
+ aa.aa_iot = sc->sc_iot;
+ aa.aa_ioh = sc->sc_ioh;
+ aa.aa_dmat = &imx_bus_dma_tag;
+ aa.aa_unit = cf->cf_loc[IMXUSBCCF_UNIT];
+ aa.aa_irq = cf->cf_loc[IMXUSBCCF_IRQ];
+
+ if (config_match(parent, cf, &aa) > 0)
+ config_attach(parent, cf, &aa, NULL);
+
+ return 0;
+}
+
Index: src/sys/arch/arm/imx/imxgpio.c
diff -u /dev/null src/sys/arch/arm/imx/imxgpio.c:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imxgpio.c Tue Nov 30 13:05:27 2010
@@ -0,0 +1,422 @@
+/* $NetBSD: imxgpio.c,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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: imxgpio.c,v 1.1 2010/11/30 13:05:27 bsh Exp $");
+
+#define _INTR_PRIVATE
+
+#include "locators.h"
+#include "gpio.h"
+
+#include <sys/param.h>
+#include <sys/evcnt.h>
+#include <sys/atomic.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/intr.h>
+
+#include <arm/cpu.h>
+#include <arm/armreg.h>
+#include <arm/cpufunc.h>
+
+#include <machine/bus.h>
+
+#include <arm/imx/imx31reg.h>
+#include <arm/imx/imx31var.h>
+#include <arm/imx/imxgpioreg.h>
+#include <arm/pic/picvar.h>
+
+#include <arm/imx/imxgpioreg.h>
+#include <arm/imx/imxgpiovar.h>
+
+#if NGPIO > 0
+/* GPIO access from userland */
+#include <sys/gpio.h>
+#include <dev/gpio/gpiovar.h>
+#endif
+
+#define MAX_NGROUP 4
+
+static void gpio_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
+static void gpio_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
+static int gpio_pic_find_pending_irqs(struct pic_softc *);
+static void gpio_pic_establish_irq(struct pic_softc *, struct intrsource *);
+
+const struct pic_ops gpio_pic_ops = {
+ .pic_unblock_irqs = gpio_pic_unblock_irqs,
+ .pic_block_irqs = gpio_pic_block_irqs,
+ .pic_find_pending_irqs = gpio_pic_find_pending_irqs,
+ .pic_establish_irq = gpio_pic_establish_irq,
+ .pic_source_name = NULL
+};
+
+struct gpio_softc {
+ device_t gpio_dev;
+ struct pic_softc gpio_pic;
+ struct intrsource *gpio_is;
+ bus_space_tag_t gpio_memt;
+ bus_space_handle_t gpio_memh;
+ uint32_t gpio_enable_mask;
+ uint32_t gpio_edge_mask;
+ uint32_t gpio_level_mask;
+#if NGPIO > 0
+ struct gpio_chipset_tag gpio_chipset;
+ gpio_pin_t gpio_pins[32];
+#endif
+};
+
+static struct {
+ bus_space_tag_t iot;
+ struct {
+ bus_space_handle_t ioh;
+ struct gpio_softc *softc;
+ } unit[MAX_NGROUP];
+} gpio_handles;
+
+extern struct cfdriver imxgpio_cd;
+
+CFATTACH_DECL_NEW(imxgpio,
+ sizeof(struct gpio_softc),
+ imxgpio_match, imxgpio_attach,
+ NULL, NULL);
+
+
+#define PIC_TO_SOFTC(pic) \
+ ((struct gpio_softc *)((char *)(pic) - \
+ offsetof(struct gpio_softc, gpio_pic)))
+
+#define GPIO_READ(gpio, reg) \
+ bus_space_read_4((gpio)->gpio_memt, (gpio)->gpio_memh, (reg))
+#define GPIO_WRITE(gpio, reg, val) \
+ bus_space_write_4((gpio)->gpio_memt, (gpio)->gpio_memh, (reg), (val))
+
+void
+gpio_pic_unblock_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask)
+{
+ struct gpio_softc * const gpio = PIC_TO_SOFTC(pic);
+ KASSERT(irq_base == 0);
+
+ gpio->gpio_enable_mask |= irq_mask;
+
+ GPIO_WRITE(gpio, GPIO_ISR, irq_mask);
+ GPIO_WRITE(gpio, GPIO_IMR, gpio->gpio_enable_mask);
+}
+
+void
+gpio_pic_block_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask)
+{
+ struct gpio_softc * const gpio = PIC_TO_SOFTC(pic);
+ KASSERT(irq_base == 0);
+
+ gpio->gpio_enable_mask &= ~irq_mask;
+ GPIO_WRITE(gpio, GPIO_IMR, gpio->gpio_enable_mask);
+}
+
+int
+gpio_pic_find_pending_irqs(struct pic_softc *pic)
+{
+ struct gpio_softc * const gpio = PIC_TO_SOFTC(pic);
+ uint32_t v;
+ uint32_t pending;
+
+ v = GPIO_READ(gpio, GPIO_ISR);
+ pending = (v & gpio->gpio_enable_mask);
+ if (pending == 0)
+ return 0;
+
+ /*
+ * Disable the pending interrupts.
+ */
+ gpio->gpio_enable_mask &= ~pending;
+ GPIO_WRITE(gpio, GPIO_IMR, gpio->gpio_enable_mask);
+
+ /*
+ * If any of the sources are edge triggered, ack them now so
+ * we won't lose them.
+ */
+ if (v & gpio->gpio_edge_mask)
+ GPIO_WRITE(gpio, GPIO_ISR, v & gpio->gpio_edge_mask);
+
+ /*
+ * Now find all the pending bits and mark them as pending.
+ */
+ do {
+ int irq;
+ KASSERT(pending != 0);
+ irq = 31 - __builtin_clz(pending);
+ pending &= ~__BIT(irq);
+ pic_mark_pending(&gpio->gpio_pic, irq);
+ } while (pending != 0);
+
+ return 1;
+}
+
+#define GPIO_TYPEMAP \
+ ((GPIO_ICR_LEVEL_LOW << (2*IST_LEVEL_LOW)) | \
+ (GPIO_ICR_LEVEL_HIGH << (2*IST_LEVEL_HIGH)) | \
+ (GPIO_ICR_EDGE_RISING << (2*IST_EDGE_RISING)) | \
+ (GPIO_ICR_EDGE_FALLING << (2*IST_EDGE_FALLING)))
+
+void
+gpio_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
+{
+ struct gpio_softc * const gpio = PIC_TO_SOFTC(pic);
+ KASSERT(is->is_irq < 32);
+ uint32_t irq_mask = __BIT(is->is_irq);
+ uint32_t v;
+ unsigned int icr_shift, icr_reg;
+ unsigned int gtype;
+
+ /*
+ * Make sure the irq isn't enabled and not asserting.
+ */
+ gpio->gpio_enable_mask &= ~irq_mask;
+ GPIO_WRITE(gpio, GPIO_ISR, irq_mask);
+ GPIO_WRITE(gpio, GPIO_IMR, gpio->gpio_enable_mask);
+ /*
+ * Convert the type to a gpio type and figure out which bits in what
+ * register we have to tweak.
+ */
+ gtype = (GPIO_TYPEMAP >> (2 * is->is_type)) & 3;
+ icr_shift = (is->is_irq & 0x0f) << 1;
+ icr_reg = GPIO_ICR1 + ((is->is_irq & 0x10) >> 2);
+
+ /*
+ * Set the interrupt type.
+ */
+ v = GPIO_READ(gpio, icr_reg);
+ v &= ~(3 << icr_shift);
+ v |= gtype << icr_shift;
+ GPIO_WRITE(gpio, icr_reg, v);
+
+ /*
+ * Mark it as input.
+ */
+ v = GPIO_READ(gpio, GPIO_DIR);
+ v &= ~irq_mask;
+ GPIO_WRITE(gpio, GPIO_DIR, v);
+
+ /*
+ * Now record the type of interrupt.
+ */
+ if (gtype == GPIO_ICR_EDGE_RISING || gtype == GPIO_ICR_EDGE_FALLING) {
+ gpio->gpio_edge_mask |= irq_mask;
+ gpio->gpio_level_mask &= ~irq_mask;
+ } else {
+ gpio->gpio_edge_mask &= ~irq_mask;
+ gpio->gpio_level_mask |= irq_mask;
+ }
+}
+
+#if NGPIO > 0
+
+static int
+imxgpio_pin_read(void *arg, int pin)
+{
+ struct gpio_softc * const gpio = arg;
+
+ return (GPIO_READ(gpio, GPIO_DR) >> pin) & 1;
+}
+
+static void
+imxgpio_pin_write(void *arg, int pin, int value)
+{
+ struct gpio_softc * const gpio = arg;
+ uint32_t mask = 1 << pin;
+ uint32_t old, new;
+
+ old = GPIO_READ(gpio, GPIO_DR);
+ if (value)
+ new = old | mask;
+ else
+ new = old & ~mask;
+
+ if (old != new)
+ GPIO_WRITE(gpio, GPIO_DR, new);
+}
+
+static void
+imxgpio_pin_ctl(void *arg, int pin, int flags)
+{
+ struct gpio_softc * const gpio = arg;
+ uint32_t mask = 1 << pin;
+ uint32_t old, new;
+
+ old = GPIO_READ(gpio, GPIO_DIR);
+ new = old;
+ switch (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
+ case GPIO_PIN_INPUT: new &= ~mask; break;
+ case GPIO_PIN_OUTPUT: new |= mask; break;
+ default: return;
+ }
+ if (old != new)
+ GPIO_WRITE(gpio, GPIO_DIR, new);
+}
+
+static void
+gpio_defer(device_t self)
+{
+ struct gpio_softc * const gpio = (void *) self;
+ struct gpio_chipset_tag * const gp = &gpio->gpio_chipset;
+ struct gpiobus_attach_args gba;
+ gpio_pin_t *pins;
+ uint32_t mask, dir, value;
+ int pin;
+
+ gp->gp_cookie = gpio;
+ gp->gp_pin_read = imxgpio_pin_read;
+ gp->gp_pin_write = imxgpio_pin_write;
+ gp->gp_pin_ctl = imxgpio_pin_ctl;
+
+ gba.gba_gc = gp;
+ gba.gba_pins = gpio->gpio_pins;
+ gba.gba_npins = __arraycount(gpio->gpio_pins);
+
+ dir = GPIO_READ(gpio, GPIO_DIR);
+ value = GPIO_READ(gpio, GPIO_DR);
+ for (pin = 0, mask = 1, pins = gpio->gpio_pins;
+ pin < 32; pin++, mask <<= 1, pins++) {
+ pins->pin_num = pin;
+ if ((gpio->gpio_edge_mask|gpio->gpio_level_mask) & mask)
+ pins->pin_caps = GPIO_PIN_INPUT;
+ else
+ pins->pin_caps = GPIO_PIN_INPUT|GPIO_PIN_OUTPUT;
+ pins->pin_flags =
+ (dir & mask) ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
+ pins->pin_state =
+ (value & mask) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+ }
+
+ config_found_ia(self, "gpiobus", &gba, gpiobus_print);
+}
+#endif /* NGPIO > 0 */
+
+void
+imxgpio_attach_common(device_t self, bus_space_tag_t iot,
+ bus_space_handle_t ioh, int index, int intr, int irqbase)
+{
+ struct gpio_softc * const gpio = device_private(self);
+
+ gpio->gpio_dev = self;
+ gpio->gpio_memt = iot;
+ gpio->gpio_memh = ioh;
+
+ if (irqbase > 0) {
+ gpio->gpio_pic.pic_ops = &gpio_pic_ops;
+ strlcpy(gpio->gpio_pic.pic_name, self->dv_xname,
+ sizeof(gpio->gpio_pic.pic_name));
+ gpio->gpio_pic.pic_maxsources = 32;
+
+ pic_add(&gpio->gpio_pic, irqbase);
+
+ aprint_normal(": interrupts %d..%d",
+ irqbase, irqbase + GPIO_NPINS - 1);
+
+ gpio->gpio_is = intr_establish(intr,
+ IPL_NET, IST_LEVEL, pic_handle_intr, &gpio->gpio_pic);
+ KASSERT( gpio->gpio_is != NULL );
+ }
+ aprint_normal("\n");
+
+
+ gpio_handles.iot = iot;
+ gpio_handles.unit[index].softc = gpio;
+ gpio_handles.unit[index].ioh = ioh;
+
+#if NGPIO > 0
+ config_interrupts(self, gpio_defer);
+#endif
+}
+
+#define GPIO_GROUP_READ(index,offset) \
+ bus_space_read_4(gpio_handles.iot, gpio_handles.unit[index].ioh, \
+ (offset))
+#define GPIO_GROUP_WRITE(index,offset,value) \
+ bus_space_write_4(gpio_handles.iot, gpio_handles.unit[index].ioh, \
+ (offset), (value))
+
+void
+gpio_set_direction(u_int gpio, u_int dir)
+{
+ int index = gpio / GPIO_NPINS;
+ int bit = gpio % GPIO_NPINS;
+ uint32_t reg;
+
+ KDASSERT(index < imxgpio_ngroups);
+
+ /* XXX lock */
+
+
+ reg = GPIO_GROUP_READ(index, GPIO_DIR);
+ if (dir == GPIO_DIR_OUT)
+ reg |= __BIT(bit);
+ else
+ reg &= ~__BIT(bit);
+ GPIO_GROUP_WRITE(index, GPIO_DIR, reg);
+
+ /* XXX unlock */
+}
+
+
+void
+gpio_data_write(u_int gpio, u_int value)
+{
+ int index = gpio / GPIO_NPINS;
+ int bit = gpio % GPIO_NPINS;
+ uint32_t reg;
+
+ KDASSERT(index < imxgpio_ngroups);
+
+ /* XXX lock */
+ reg = GPIO_GROUP_READ(index, GPIO_DR);
+ if (value)
+ reg |= __BIT(bit);
+ else
+ reg &= ~__BIT(bit);
+ GPIO_GROUP_WRITE(index, GPIO_DR, reg);
+
+ /* XXX unlock */
+}
+
+bool
+gpio_data_read(u_int gpio)
+{
+ int index = gpio / GPIO_NPINS;
+ int bit = gpio % GPIO_NPINS;
+ uint32_t reg;
+
+ KDASSERT(index < imxgpio_ngroups);
+
+ reg = GPIO_GROUP_READ(index, GPIO_DR);
+
+ return reg & __BIT(bit) ? true : false;
+}
Index: src/sys/arch/arm/imx/imxgpiovar.h
diff -u /dev/null src/sys/arch/arm/imx/imxgpiovar.h:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imxgpiovar.h Tue Nov 30 13:05:27 2010
@@ -0,0 +1,53 @@
+/* $NetBSD: imxgpiovar.h,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+#ifndef _ARM_IMX_IMXGRPIOVAR_H
+#define _ARM_IMX_IMXGRPIOVAR_H
+
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <arm/imx/imxgpioreg.h> /* for GPIO_NPINS */
+
+void imxgpio_attach_common(device_t, bus_space_tag_t, bus_space_handle_t,
+ int, int, int);
+/* defined imx[35]1_gpio.c */
+extern const int imxgpio_ngroups;
+int imxgpio_match(device_t, cfdata_t, void *);
+void imxgpio_attach(device_t, device_t, void *);
+
+
+#define GPIO_NO(group, pin) (((group) - 1) * GPIO_NPINS + (pin))
+#define GPIO_MODULE(pin) ((pin) / GPIO_NPINS)
+
+/* in-kernel GPIO access utility functions */
+enum GPIO_DIRECTION {GPIO_DIR_IN, GPIO_DIR_OUT};
+void gpio_set_direction(u_int, enum GPIO_DIRECTION);
+void gpio_data_write(u_int, u_int);
+bool gpio_data_read(u_int);
+#endif /* _ARM_IMX_IMXGRPIOVAR_H */
Index: src/sys/arch/arm/imx/imxusb.c
diff -u /dev/null src/sys/arch/arm/imx/imxusb.c:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imxusb.c Tue Nov 30 13:05:27 2010
@@ -0,0 +1,402 @@
+/* $NetBSD: imxusb.c,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+/*
+ * Copyright (c) 2009, 2010 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi and Hiroyuki Bessho 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.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imxusb.c,v 1.1 2010/11/30 13:05:27 bsh Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/bus.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
+
+#include <arm/imx/imxusbreg.h>
+#include <arm/imx/imxusbvar.h>
+#include <arm/imx/imxgpiovar.h>
+#include "locators.h"
+
+#include <dev/usb/ulpireg.h> /* for test */
+
+static int imxehci_match(device_t, cfdata_t, void *);
+static void imxehci_attach(device_t, device_t, void *);
+
+uint8_t imxusb_ulpi_read(struct imxehci_softc *sc, int addr);
+void imxusb_ulpi_write(struct imxehci_softc *sc, int addr, uint8_t data);
+static void ulpi_reset(struct imxehci_softc *sc);
+
+
+
+/* attach structures */
+CFATTACH_DECL_NEW(imxehci, sizeof(struct imxehci_softc),
+ imxehci_match, imxehci_attach, NULL, NULL);
+
+static int
+imxehci_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct imxusbc_attach_args *aa = aux;
+
+ if (aa->aa_unit < 0 || 3 < aa->aa_unit) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+imxehci_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxusbc_attach_args *aa = aux;
+ struct imxusbc_softc *usbc = device_private(parent);
+ struct imxehci_softc *sc = device_private(self);
+ ehci_softc_t *hsc = &sc->sc_hsc;
+ bus_space_tag_t iot;
+ uint16_t hcirev;
+ usbd_status r;
+ uint32_t id, hwhost, hwdevice;
+ const char *comma;
+
+ sc->sc_hsc.sc_dev = self;
+ iot = sc->sc_iot = sc->sc_hsc.iot = aa->aa_iot;
+ sc->sc_unit = aa->aa_unit;
+ sc->sc_usbc = usbc;
+ hsc->sc_bus.hci_private = sc;
+
+ aprint_normal("\n");
+
+ /* per unit registers */
+ if (bus_space_subregion(iot, aa->aa_ioh,
+ aa->aa_unit * IMXUSB_EHCI_SIZE, IMXUSB_EHCI_SIZE,
+ &sc->sc_ioh) ||
+ bus_space_subregion(iot, aa->aa_ioh,
+ aa->aa_unit * IMXUSB_EHCI_SIZE + IMXUSB_EHCIREGS,
+ IMXUSB_EHCI_SIZE - IMXUSB_EHCIREGS,
+ &sc->sc_hsc.ioh)) {
+
+ aprint_error_dev(self, "can't subregion\n");
+ return;
+ }
+
+ id = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_ID);
+ hcirev = bus_space_read_2(iot, sc->sc_hsc.ioh, EHCI_HCIVERSION);
+
+ aprint_normal_dev(self,
+ "i.MX USB Controller id=%d revision=%d HCI revision=0x%x\n",
+ id & (uint32_t)IMXUSB_ID_ID_MASK,
+ (id & (uint32_t)IMXUSB_ID_REVISION_MASK) >>
+ IMXUSB_ID_REVISION_SHIFT,
+ hcirev);
+
+ hwhost = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_HWHOST);
+ hwdevice = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_HWDEVICE);
+
+ aprint_normal_dev(self, "");
+
+ comma = "";
+ if (hwhost & HWHOST_HC) {
+ int n_ports = 1 + ((hwhost & HWHOST_NPORT_MASK) >>
+ HWHOST_NPORT_SHIFT);
+ aprint_normal("%d host port%s",
+ n_ports, n_ports > 1 ? "s" : "");
+ comma = ", ";
+ }
+
+ if (hwdevice & HWDEVICE_DC) {
+ int n_endpoints = (hwdevice & HWDEVICE_DEVEP_MASK) >>
+ HWDEVICE_DEVEP_SHIFT;
+ aprint_normal("%sdevice capable, %d endpoint%s",
+ comma,
+ n_endpoints, n_endpoints > 1 ? "s" : "");
+ }
+ aprint_normal("\n");
+
+ sc->sc_hsc.sc_bus.dmatag = aa->aa_dmat;
+
+ sc->sc_hsc.sc_offs = bus_space_read_1(iot, sc->sc_hsc.ioh,
+ EHCI_CAPLENGTH);
+
+ /* Platform dependent setup */
+ if (usbc->sc_init_md_hook)
+ usbc->sc_init_md_hook(sc);
+
+
+ imxehci_reset(sc);
+ imxehci_select_interface(sc, sc->sc_iftype);
+
+ if (sc->sc_iftype == IMXUSBC_IF_ULPI) {
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW, 0);
+
+ aprint_normal_dev(hsc->sc_dev,
+ "ULPI phy VID 0x%04x PID 0x%04x\n",
+ (imxusb_ulpi_read(sc, ULPI_VENDOR_ID_LOW) |
+ imxusb_ulpi_read(sc, ULPI_VENDOR_ID_HIGH) << 8),
+ (imxusb_ulpi_read(sc, ULPI_PRODUCT_ID_LOW) |
+ imxusb_ulpi_read(sc, ULPI_PRODUCT_ID_HIGH) << 8));
+
+ ulpi_reset(sc);
+
+ }
+
+ imxehci_host_mode(sc);
+
+ if (usbc->sc_setup_md_hook)
+ usbc->sc_setup_md_hook(sc, IMXUSB_HOST);
+ else if (sc->sc_iftype == IMXUSBC_IF_ULPI) {
+ imxusb_ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR,
+ OTG_CONTROL_IDPULLUP);
+
+ imxusb_ulpi_write(sc, ULPI_OTG_CONTROL + ULPI_REG_SET,
+ OTG_CONTROL_USEEXTVBUSIND |
+ OTG_CONTROL_DRVVBUSEXT |
+ OTG_CONTROL_DRVVBUS |
+ OTG_CONTROL_CHRGVBUS
+ );
+ }
+
+ /* Disable interrupts, so we don't get any spurious ones. */
+ EOWRITE2(hsc, EHCI_USBINTR, 0);
+
+ intr_establish(aa->aa_irq, IPL_USB, IST_LEVEL, ehci_intr, hsc);
+
+ /* Figure out vendor for root hub descriptor. */
+ strlcpy(hsc->sc_vendor, "i.MX", sizeof(hsc->sc_vendor));
+
+ r = ehci_init(hsc);
+ if (r != USBD_NORMAL_COMPLETION) {
+ aprint_error_dev(self, "init failed, error=%d\n", r);
+ return;
+ }
+
+ /* Attach usb device. */
+ hsc->sc_child = config_found(self, &hsc->sc_bus, usbctlprint);
+}
+
+
+
+
+void
+imxehci_select_interface(struct imxehci_softc *sc, enum imx_usb_if interface)
+{
+ uint32_t reg;
+ struct ehci_softc *hsc = &sc->sc_hsc;
+
+ reg = EOREAD4(hsc, EHCI_PORTSC(1));
+ reg = (reg & ~PORTSC_PTS_MASK) | (interface << PORTSC_PTS_SHIFT);
+ EOWRITE4(hsc, EHCI_PORTSC(1), reg);
+}
+
+
+static uint32_t
+ulpi_wakeup(struct imxehci_softc *sc, int tout)
+{
+ uint32_t ulpi_view;
+ int i = 0;
+ ulpi_view = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW);
+
+ if ( !(ulpi_view & ULPI_SS) ) {
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+ IMXUSB_ULPIVIEW, ULPI_WU);
+ for (i = 0; (tout < 0) || (i < tout); i++) {
+ ulpi_view = bus_space_read_4(sc->sc_iot,
+ sc->sc_ioh, IMXUSB_ULPIVIEW);
+ if ( !(ulpi_view & ULPI_WU) )
+ break;
+ delay(1);
+ };
+ }
+
+ if ((tout > 0) && (i >= tout)) {
+ aprint_error_dev(sc->sc_hsc.sc_dev, "%s: timeout\n", __func__);
+ }
+
+ return ulpi_view;
+}
+
+static uint32_t
+ulpi_wait(struct imxehci_softc *sc, int tout)
+{
+ uint32_t ulpi_view;
+ int i;
+ ulpi_view = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW);
+
+ for (i = 0; (tout < 0) | (i < tout); i++) {
+ ulpi_view = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ IMXUSB_ULPIVIEW);
+ if (!(ulpi_view & ULPI_RUN))
+ break;
+ delay(1);
+ }
+
+ if ((tout > 0) && (i >= tout)) {
+ aprint_error_dev(sc->sc_hsc.sc_dev, "%s: timeout\n", __func__);
+ }
+
+ return ulpi_view;
+}
+
+#define TIMEOUT 100000
+
+uint8_t
+imxusb_ulpi_read(struct imxehci_softc *sc, int addr)
+{
+ uint32_t data;
+
+ ulpi_wakeup(sc, TIMEOUT);
+
+ data = ULPI_RUN | (addr << ULPI_ADDR_SHIFT);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW, data);
+
+ data = ulpi_wait(sc, TIMEOUT);
+
+ return (data & ULPI_DATRD_MASK) >> ULPI_DATRD_SHIFT;
+}
+
+void
+imxusb_ulpi_write(struct imxehci_softc *sc, int addr, uint8_t data)
+{
+ uint32_t reg;
+
+ ulpi_wakeup(sc, TIMEOUT);
+
+ reg = ULPI_RUN | ULPI_RW | ((addr) << ULPI_ADDR_SHIFT) | data;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW, reg);
+
+ ulpi_wait(sc, TIMEOUT);
+
+ return;
+}
+
+#if 0
+static int
+ulpi_scratch_test(struct imxehci_softc *sc)
+{
+ uint32_t ulpi_view;
+
+ ulpi_view = ulpi_wakeup(sc, 1000);
+ if (ulpi_view & ULPI_WU) {
+ return -1;
+ }
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW,
+ (ULPI_RUN | ULPI_RW |
+ (ULPI_SCRATCH << ULPI_ADDR_SHIFT) | 0xAA));
+
+ ulpi_view = ulpi_wait(sc, 1000);
+
+ if (ulpi_view & ULPI_RUN) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static void
+ulpi_reset(struct imxehci_softc *sc)
+{
+ uint8_t data;
+ int timo = 1000 * 1000; /* XXXX: 1sec */
+
+ imxusb_ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET,
+ FUNCTION_CONTROL_RESET /*0x20*/);
+ do {
+ data = imxusb_ulpi_read(sc, ULPI_FUNCTION_CONTROL);
+ if (!(data & FUNCTION_CONTROL_RESET))
+ break;
+ delay(100);
+ timo -= 100;
+ } while (timo > 0);
+ if (timo <= 0) {
+ aprint_error_dev(sc->sc_hsc.sc_dev, "%s: reset failed!!\n",
+ __func__);
+ return;
+ }
+
+ return;
+}
+
+void
+imxehci_reset(struct imxehci_softc *sc)
+{
+ u_int32_t reg;
+ int i;
+ struct ehci_softc *hsc = &sc->sc_hsc;
+#define RESET_TIMEOUT 100
+
+ reg = EOREAD4(hsc, EHCI_USBCMD);
+ reg &= ~EHCI_CMD_RS;
+ EOWRITE4(hsc, EHCI_USBCMD, reg);
+
+ for (i=0; i < RESET_TIMEOUT; ++i) {
+ reg = EOREAD4(hsc, EHCI_USBCMD);
+ if ((reg & EHCI_CMD_RS) == 0)
+ break;
+ usb_delay_ms(&hsc->sc_bus, 1);
+ }
+
+ EOWRITE4(hsc, EHCI_USBCMD, reg | EHCI_CMD_HCRESET);
+ for (i = 0; i < RESET_TIMEOUT; i++) {
+ reg = EOREAD4(hsc, EHCI_USBCMD);
+ if ((reg & EHCI_CMD_HCRESET) == 0)
+ break;
+ usb_delay_ms(&hsc->sc_bus, 1);
+ }
+ if (i >= RESET_TIMEOUT) {
+ aprint_error_dev(hsc->sc_dev, "reset timeout (%x)\n", reg);
+ }
+
+ usb_delay_ms(&hsc->sc_bus, 100);
+}
+
+void
+imxehci_host_mode(struct imxehci_softc *sc)
+{
+ struct ehci_softc *hsc = &sc->sc_hsc;
+ uint32_t reg;
+
+ reg = EOREAD4(hsc, EHCI_PORTSC(1));
+ reg &= ~(EHCI_PS_CSC | EHCI_PS_PEC | EHCI_PS_OCC);
+ reg |= EHCI_PS_PP | EHCI_PS_PE;
+ EOWRITE4(hsc, EHCI_PORTSC(1), reg);
+
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXUSB_OTGSC);
+ reg |= OTGSC_IDPU;
+ reg |= OTGSC_DPIE | OTGSC_IDIE;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_OTGSC, reg);
+
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXUSB_OTGMODE);
+ reg |= USBMODE_HOST;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_OTGMODE, reg);
+}
Index: src/sys/arch/arm/imx/imxusbreg.h
diff -u /dev/null src/sys/arch/arm/imx/imxusbreg.h:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imxusbreg.h Tue Nov 30 13:05:27 2010
@@ -0,0 +1,113 @@
+/* $NetBSD: imxusbreg.h,v 1.1 2010/11/30 13:05:27 bsh Exp $ */
+/*
+ * Copyright (c) 2009, 2010 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_IMXUSBREG_H
+#define _ARM_IMX_IMXUSBREG_H
+
+#define IMXUSB_ID 0x0000
+#define IMXUSB_ID_ID_MASK __BITS(5,0)
+#define IMXUSB_ID_REVISION_SHIFT 16
+#define IMXUSB_ID_REVISION_MASK __BITS(IMXUSB_ID_REVISION_SHIFT,23)
+#define IMXUSB_HWGENERAL 0x0004
+#define IMXUSB_HWHOST 0x0008
+#define HWHOST_HC __BIT(0)
+#define HWHOST_NPORT_SHIFT 1
+#define HWHOST_NPORT_MASK __BITS(HWHOST_NPORT_SHIFT,3)
+#define IMXUSB_HWDEVICE 0x000c
+#define HWDEVICE_DC __BIT(0)
+#define HWDEVICE_DEVEP_SHIFT 1
+#define HWDEVICE_DEVEP_MASK __BITS(HWDEVICE_DEVEP_SHIFT,5)
+#define IMXUSB_HWTXBUF 0x0010
+#define IMXUSB_HWRXBUF 0x0014
+
+#define IMXUSB_EHCIREGS 0x0100
+
+#define IMXUSB_ULPIVIEW 0x0170
+#define ULPI_WU __BIT(31)
+#define ULPI_RUN __BIT(30)
+#define ULPI_RW __BIT(29)
+#define ULPI_SS __BIT(27)
+#define ULPI_PORT_SHIFT 24
+#define ULPI_PORT_MASK (0x7 << ULPI_PORT_SHIFT)
+#define ULPI_ADDR_SHIFT 16
+#define ULPI_ADDR_MASK (0xff << ULPI_ADDR_SHIFT)
+#define ULPI_DATRD_SHIFT 8
+#define ULPI_DATRD_MASK (0xff << ULPI_DATRD_SHIFT)
+#define ULPI_DATWR_SHIFT 0
+#define ULPI_DATWR_MASK (0xff << ULPI_DATWR_SHIFT)
+
+#define IMXUSB_OTGSC 0x01A4
+#define OTGSC_DPIE __BIT(30)
+#define OTGSC_1MSE __BIT(29)
+#define OTGSC_BSEIE __BIT(28)
+#define OTGSC_BSVIE __BIT(27)
+#define OTGSC_ASVIE __BIT(26)
+#define OTGSC_AVVIE __BIT(25)
+#define OTGSC_IDIE __BIT(24)
+#define OTGSC_DPIS __BIT(22)
+#define OTGSC_1MSS __BIT(21)
+#define OTGSC_BSEIS __BIT(20)
+#define OTGSC_BSVIS __BIT(19)
+#define OTGSC_ASVIS __BIT(18)
+#define OTGSC_AVVIS __BIT(17)
+#define OTGSC_IDIS __BIT(16)
+#define OTGSC_DPS __BIT(14)
+#define OTGSC_1MST __BIT(13)
+#define OTGSC_BSE __BIT(12)
+#define OTGSC_BSV __BIT(11)
+#define OTGSC_ASV __BIT(10)
+#define OTGSC_AVV __BIT( 9)
+#define OTGSC_ID __BIT( 8)
+#define OTGSC_IDPU __BIT( 5)
+#define OTGSC_DP __BIT( 4)
+#define OTGSC_OT __BIT( 3)
+#define OTGSC_VC __BIT( 1)
+#define OTGSC_VD __BIT( 0)
+#define IMXUSB_OTGMODE 0x01A8
+#define USBMODE_DEVICE (0x2 << 0)
+#define USBMODE_HOST (0x3 << 0)
+
+#define IMXUSB_EHCI_SIZE 0x200
+
+
+/* extension to PORTSCx register of EHCI. */
+#define PORTSC_PTS_SHIFT 30
+#define PORTSC_PTS_MASK __BITS(PORTSC_PTS_SHIFT,31)
+#define PORTSC_PTS_UTMI (0 << PORTSC_PTS_SHIFT)
+#define PORTSC_PTS_PHILIPS (1 << PORTSC_PTS_SHIFT) /* not in i.MX51*/
+#define PORTSC_PTS_ULPI (2 << PORTSC_PTS_SHIFT)
+#define PORTSC_PTS_SERIAL (3 << PORTSC_PTS_SHIFT)
+
+#define PORTSC_STS __BIT(29) /* serial transeiver select */
+#define PORTSC_PTW __BIT(28) /* parallel transceiver width */
+#define PORTSC_PTW_8 0
+#define PORTSC_PTW_16 PORT_SC_PTW
+#define PORTSC_PSPD __BITS(26,27) /* port speed (RO) */
+#define PORTSC_PFSC __BIT(24) /* port force full speed */
+#define PORTSC_PHCD __BIT(23) /* PHY low power suspend */
+
+#endif /* _ARM_IMX_IMXUSBREG_H */
Index: src/sys/arch/arm/imx/imxusbvar.h
diff -u /dev/null src/sys/arch/arm/imx/imxusbvar.h:1.1
--- /dev/null Tue Nov 30 13:05:27 2010
+++ src/sys/arch/arm/imx/imxusbvar.h Tue Nov 30 13:05:27 2010
@@ -0,0 +1,51 @@
+#ifndef _ARM_IMX_IMXUSBVAR_H
+#define _ARM_IMX_IMXUSBVAR_H
+
+struct imxehci_softc;
+
+enum imx_usb_role {
+ IMXUSB_HOST,
+ IMXUSB_DEVICE
+};
+
+struct imxusbc_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ /* filled in by platform dependent routine */
+ void (* sc_init_md_hook)(struct imxehci_softc *);
+ void (* sc_setup_md_hook)(struct imxehci_softc *, enum imx_usb_role);
+};
+
+struct imxusbc_attach_args {
+ bus_space_tag_t aa_iot;
+ bus_space_handle_t aa_ioh;
+ bus_dma_tag_t aa_dmat;
+ int aa_unit; /* 0: OTG, 1: HOST1, 2: HOST2 ... */
+ int aa_irq;
+};
+
+enum imx_usb_if {
+ IMXUSBC_IF_UTMI,
+ IMXUSBC_IF_PHILIPS,
+ IMXUSBC_IF_ULPI,
+ IMXUSBC_IF_SERIAL
+};
+
+struct imxehci_softc {
+ ehci_softc_t sc_hsc;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ struct imxusbc_softc *sc_usbc;
+ uint sc_unit;
+ enum imx_usb_if sc_iftype;
+};
+
+int imxusbc_attach_common(device_t, device_t, bus_space_tag_t);
+void imxehci_select_interface(struct imxehci_softc *, enum imx_usb_if);
+void imxehci_host_mode(struct imxehci_softc *);
+void imxehci_reset(struct imxehci_softc *);
+
+#endif /* _ARM_IMX_IMXUSBVAR_H */