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 <r...@nerv.org> @@ -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 */