[U-Boot] [PATCH 0/3] msm7630 usb gadget and emmc support

This patch series contains support for usb gadget, enabling eMMC high capacity and interrupt support for msm7630 surf.
Mohamed Haneef (3): MSM7630 Interrupt support MSM7630 gadget usb support board: qcom: enable high capacity eMMC cards
arch/arm/cpu/armv7/msm7630/Makefile | 1 + arch/arm/cpu/armv7/msm7630/interrupts.c | 155 +++++++ arch/arm/include/asm/arch-msm7630/exclusion.h | 42 ++ arch/arm/include/asm/arch-msm7630/hsusb.h | 182 ++++++++ arch/arm/include/asm/arch-msm7630/interrupts.h | 40 ++ arch/arm/include/asm/arch-msm7630/irqs.h | 173 ++++++++ board/qcom/msm7630_surf/msm7630_surf.c | 5 +- drivers/serial/usbtty.h | 2 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/msm_udc.c | 560 ++++++++++++++++++++++++ include/configs/msm7630_surf.h | 12 +- include/usb/msm_udc.h | 46 ++ 12 files changed, 1215 insertions(+), 4 deletions(-) create mode 100644 arch/arm/cpu/armv7/msm7630/interrupts.c create mode 100644 arch/arm/include/asm/arch-msm7630/exclusion.h create mode 100644 arch/arm/include/asm/arch-msm7630/hsusb.h create mode 100644 arch/arm/include/asm/arch-msm7630/interrupts.h create mode 100644 arch/arm/include/asm/arch-msm7630/irqs.h create mode 100644 drivers/usb/gadget/msm_udc.c create mode 100644 include/usb/msm_udc.h

* Support for msm7630 interrupts
Signed-off-by: Mohamed Haneef mohamed.haneef@lntinfotech.com --- arch/arm/cpu/armv7/msm7630/Makefile | 1 + arch/arm/cpu/armv7/msm7630/interrupts.c | 155 +++++++++++++++++++++ arch/arm/include/asm/arch-msm7630/exclusion.h | 42 ++++++ arch/arm/include/asm/arch-msm7630/interrupts.h | 40 ++++++ arch/arm/include/asm/arch-msm7630/irqs.h | 173 ++++++++++++++++++++++++ board/qcom/msm7630_surf/msm7630_surf.c | 3 + 6 files changed, 414 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/armv7/msm7630/interrupts.c create mode 100644 arch/arm/include/asm/arch-msm7630/exclusion.h create mode 100644 arch/arm/include/asm/arch-msm7630/interrupts.h create mode 100644 arch/arm/include/asm/arch-msm7630/irqs.h
diff --git a/arch/arm/cpu/armv7/msm7630/Makefile b/arch/arm/cpu/armv7/msm7630/Makefile index b97026f..b106ddc 100644 --- a/arch/arm/cpu/armv7/msm7630/Makefile +++ b/arch/arm/cpu/armv7/msm7630/Makefile @@ -40,6 +40,7 @@ COBJS-y := board.o COBJS-y += timer.o COBJS-y += acpuclock.o COBJS-y += gpio.o +COBJS-$(CONFIG_USE_IRQ) += interrupts.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS-y)) diff --git a/arch/arm/cpu/armv7/msm7630/interrupts.c b/arch/arm/cpu/armv7/msm7630/interrupts.c new file mode 100644 index 0000000..6cae9c8 --- /dev/null +++ b/arch/arm/cpu/armv7/msm7630/interrupts.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2008, Google Inc. + * All rights reserved. + * + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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 <common.h> +#include <asm/io.h> +#include <asm/arch/interrupts.h> +#include <asm/arch/irqs.h> +#include <asm/arch/iomap.h> +#include <asm/arch/exclusion.h> + +#define VIC_REG(off) (MSM_VIC_BASE + (off)) + +#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_EN0 VIC_REG(0x0010) +#define VIC_INT_EN1 VIC_REG(0x0014) +#define VIC_INT_ENCLEAR0 VIC_REG(0x0020) +#define VIC_INT_ENCLEAR1 VIC_REG(0x0024) +#define VIC_INT_ENSET0 VIC_REG(0x0030) +#define VIC_INT_ENSET1 VIC_REG(0x0034) +#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */ +#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */ +#define VIC_NO_PEND_VAL VIC_REG(0x0060) +#define VIC_INT_MASTEREN VIC_REG(0x0068) /* 1: IRQ, 2: FIQ */ +#define VIC_CONFIG VIC_REG(0x006C) /* 1: USE ARM1136 VIC */ +#define VIC_SECURITY0 VIC_REG(0x0070) +#define VIC_SECURITY1 VIC_REG(0x0074) +#define VIC_IRQ_STATUS0 VIC_REG(0x0080) +#define VIC_IRQ_STATUS1 VIC_REG(0x0084) +#define VIC_FIQ_STATUS0 VIC_REG(0x0090) +#define VIC_FIQ_STATUS1 VIC_REG(0x0094) +#define VIC_RAW_STATUS0 VIC_REG(0x00A0) +#define VIC_RAW_STATUS1 VIC_REG(0x00A4) +#define VIC_INT_CLEAR0 VIC_REG(0x00B0) +#define VIC_INT_CLEAR1 VIC_REG(0x00B4) +#define VIC_SOFTINT0 VIC_REG(0x00C0) +#define VIC_SOFTINT1 VIC_REG(0x00C4) +#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */ +#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */ +#define VIC_IRQ_VEC_WR VIC_REG(0x00D8) +#define VIC_FIQ_VEC_RD VIC_REG(0x00DC) /* pending int # */ +#define VIC_FIQ_VEC_PEND_RD VIC_REG(0x00E0) /* pending vector addr */ +#define VIC_FIQ_VEC_WR VIC_REG(0x00E4) +#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E8) +#define VIC_IRQ_IN_STACK VIC_REG(0x00EC) +#define VIC_FIQ_IN_SERVICE VIC_REG(0x00F0) +#define VIC_FIQ_IN_STACK VIC_REG(0x00F4) +#define VIC_TEST_BUS_SEL VIC_REG(0x00F8) + +#define SIRC_REG(off) (MSM_SIRC_BASE + (off)) + +#define SIRC_INT_SELECT SIRC_REG(0x0000) /* 0: IRQ0 1: IRQ1 */ +#define SIRC_INT_ENABLE SIRC_REG(0x0004) +#define SIRC_INT_ENCLEAR SIRC_REG(0x0008) +#define SIRC_INT_ENSET SIRC_REG(0x000C) +#define SIRC_INT_TYPE SIRC_REG(0x0010) /* 1: EDGE, 0: LEVEL */ +#define SIRC_INT_POLARITY SIRC_REG(0x0014) /* 1: NEG, 0: POS */ +#define SIRC_SECURITY SIRC_REG(0x0018) /* 0: SEC, 1: NSEC */ +#define SIRC_IRQ0_STATUS SIRC_REG(0x001C) +#define SIRC_IRQ1_STATUS SIRC_REG(0x0020) +#define SIRC_RAW_STATUS SIRC_REG(0x0024) + +struct ihandler { + int_handler func; + void *arg; +}; + +static struct ihandler handler[NR_IRQS]; + +int arch_interrupt_init(void) +{ + writel(0xffffffff, VIC_INT_CLEAR0); + writel(0xffffffff, VIC_INT_CLEAR1); + writel(0, VIC_INT_SELECT0); + writel(0, VIC_INT_SELECT1); + writel(0xffffffff, VIC_INT_TYPE0); + writel(0xffffffff, VIC_INT_TYPE1); + writel(0, VIC_CONFIG); + writel(1, VIC_INT_MASTEREN); + return 0; +} + +void do_irq(struct pt_regs *pt_regs) +{ + unsigned num; + enum handler_return ret; + num = readl(VIC_IRQ_VEC_RD); + num = readl(VIC_IRQ_VEC_PEND_RD); + if (num > NR_IRQS) + return; + (void) handler[num].func(handler[num].arg); + writel(1 << (num & 31), (num > 31) ? VIC_INT_CLEAR1 : VIC_INT_CLEAR0); + writel(0, VIC_IRQ_VEC_WR); +} + +int mask_interrupt(unsigned int vector) +{ + unsigned reg = (vector > 31) ? VIC_INT_ENCLEAR1 : VIC_INT_ENCLEAR0; + unsigned bit = 1 << (vector & 31); + writel(bit, reg); + return 0; +} + +int unmask_interrupt(unsigned int vector) +{ + unsigned reg = (vector > 31) ? VIC_INT_ENSET1 : VIC_INT_ENSET0; + unsigned bit = 1 << (vector & 31); + writel(bit, reg); + return 0; +} + +void register_int_handler(unsigned int vector, int_handler func, void *arg) +{ + if (vector >= NR_IRQS) { + debug("could not set interrupt %#08x", vector); + return; + } + enter_critical_section(); + handler[vector].func = func; + handler[vector].arg = arg; + exit_critical_section(); +} diff --git a/arch/arm/include/asm/arch-msm7630/exclusion.h b/arch/arm/include/asm/arch-msm7630/exclusion.h new file mode 100644 index 0000000..e98716e --- /dev/null +++ b/arch/arm/include/asm/arch-msm7630/exclusion.h @@ -0,0 +1,42 @@ +/* + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __EXCLUSION_H +#define __EXCLUSION_H +#include <common.h> + +/* critical sections */ +extern int critical_section_count; + +static inline __attribute__((always_inline)) void enter_critical_section(void) +{ + critical_section_count++; + if (critical_section_count == 1) + disable_interrupts(); +} + +static inline __attribute__((always_inline)) void exit_critical_section(void) +{ + critical_section_count--; + if (critical_section_count == 0) + enable_interrupts(); +} + +#endif diff --git a/arch/arm/include/asm/arch-msm7630/interrupts.h b/arch/arm/include/asm/arch-msm7630/interrupts.h new file mode 100644 index 0000000..e7b95de --- /dev/null +++ b/arch/arm/include/asm/arch-msm7630/interrupts.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __PLATFORM_INTERRUPTS_H +#define __PLATFORM_INTERRUPTS_H + +enum handler_return { + INT_NO_RESCHEDULE = 0, + INT_RESCHEDULE, +}; + + +typedef enum handler_return (*int_handler)(void *arg); + +void register_int_handler(unsigned int vector, int_handler handler, void *arg); +int mask_interrupt(unsigned int vector); +int unmask_interrupt(unsigned int vector); +#endif diff --git a/arch/arm/include/asm/arch-msm7630/irqs.h b/arch/arm/include/asm/arch-msm7630/irqs.h new file mode 100644 index 0000000..2310e3e --- /dev/null +++ b/arch/arm/include/asm/arch-msm7630/irqs.h @@ -0,0 +1,173 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __ASM_ARCH_MSM_IRQS_7X30_H +#define __ASM_ARCH_MSM_IRQS_7X30_H + +/* MSM ACPU Interrupt Numbers */ + +#define INT_DEBUG_TIMER_EXP 0 +#define INT_GPT0_TIMER_EXP 1 +#define INT_GPT1_TIMER_EXP 2 +#define INT_WDT0_ACCSCSSBARK 3 +#define INT_WDT1_ACCSCSSBARK 4 +#define INT_AVS_SVIC 5 +#define INT_AVS_SVIC_SW_DONE 6 +#define INT_SC_DBG_RX_FULL 7 +#define INT_SC_DBG_TX_EMPTY 8 +#define INT_SC_PERF_MON 9 +#define INT_AVS_REQ_DOWN 10 +#define INT_AVS_REQ_UP 11 +#define INT_SC_ACG 12 +/* SCSS_VICFIQSTS1[13:15] are RESERVED */ +#define INT_L2_SVICCPUIRPTREQ 16 +#define INT_L2_SVICDMANSIRPTREQ 17 +#define INT_L2_SVICDMASIRPTREQ 18 +#define INT_L2_SVICSLVIRPTREQ 19 +#define INT_AD5A_MPROC_APPS_0 20 +#define INT_AD5A_MPROC_APPS_1 21 +#define INT_A9_M2A_0 22 +#define INT_A9_M2A_1 23 +#define INT_A9_M2A_2 24 +#define INT_A9_M2A_3 25 +#define INT_A9_M2A_4 26 +#define INT_A9_M2A_5 27 +#define INT_A9_M2A_6 28 +#define INT_A9_M2A_7 29 +#define INT_A9_M2A_8 30 +#define INT_A9_M2A_9 31 + +#define INT_AXI_EBI1_SC (32 + 0) +#define INT_IMEM_ERR (32 + 1) +#define INT_AXI_EBI0_SC (32 + 2) +#define INT_PBUS_SC_IRQC (32 + 3) +#define INT_PERPH_BUS_BPM (32 + 4) +#define INT_CC_TEMP_SENSE (32 + 5) +#define INT_UXMC_EBI0 (32 + 6) +#define INT_UXMC_EBI1 (32 + 7) +#define INT_EBI2_OP_DONE (32 + 8) +#define INT_EBI2_WR_ER_DONE (32 + 9) +#define INT_TCSR_SPSS_CE (32 + 10) +#define INT_EMDH (32 + 11) +#define INT_PMDH (32 + 12) +#define INT_MDC (32 + 13) +#define INT_MIDI_TO_SUPSS (32 + 14) +#define INT_LPA_2 (32 + 15) +#define INT_GPIO_GROUP1_SECURE (32 + 16) +#define INT_GPIO_GROUP2_SECURE (32 + 17) +#define INT_GPIO_GROUP1 (32 + 18) +#define INT_GPIO_GROUP2 (32 + 19) +#define INT_MPRPH_SOFTRESET (32 + 20) +#define INT_PWB_I2C (32 + 21) +#define INT_PWB_I2C_2 (32 + 22) +#define INT_TSSC_SAMPLE (32 + 23) +#define INT_TSSC_PENUP (32 + 24) +#define INT_TCHSCRN_SSBI (32 + 25) +#define INT_FM_RDS (32 + 26) +#define INT_KEYSENSE (32 + 27) +#define INT_USB_OTG_HS (32 + 28) +#define INT_USB_OTG_HS2 (32 + 29) +#define INT_USB_OTG_HS3 (32 + 30) +#define INT_RESERVED_BIT31 (32 + 31) + +#define INT_SPI_OUTPUT (64 + 0) +#define INT_SPI_INPUT (64 + 1) +#define INT_SPI_ERROR (64 + 2) +#define INT_UART1 (64 + 3) +#define INT_UART1_RX (64 + 4) +#define INT_UART2 (64 + 5) +#define INT_UART2_RX (64 + 6) +#define INT_UART3 (64 + 7) +#define INT_UART3_RX (64 + 8) +#define INT_UART1DM_IRQ (64 + 9) +#define INT_UART1DM_RX (64 + 10) +#define INT_UART2DM_IRQ (64 + 11) +#define INT_UART2DM_RX (64 + 12) +#define INT_TSIF (64 + 13) +#define INT_ADM_SC1 (64 + 14) +#define INT_ADM_SC2 (64 + 15) +#define INT_MDP (64 + 16) +#define INT_VPE (64 + 17) +#define INT_GRP_2D (64 + 18) +#define INT_GRP_3D (64 + 19) +#define INT_ROTATOR (64 + 20) +#define INT_MFC720 (64 + 21) +#define INT_JPEG (64 + 22) +#define INT_VFE (64 + 23) +#define INT_TV_ENC (64 + 24) +#define INT_PMIC_SSBI (64 + 25) +#define INT_MPM_1 (64 + 26) +#define INT_TCSR_SPSS_SAMPLE (64 + 27) +#define INT_TCSR_SPSS_PENUP (64 + 28) +#define INT_MPM_2 (64 + 29) +#define INT_SDC1_0 (64 + 30) +#define INT_SDC1_1 (64 + 31) + +#define INT_SDC3_0 (96 + 0) +#define INT_SDC3_1 (96 + 1) +#define INT_SDC2_0 (96 + 2) +#define INT_SDC2_1 (96 + 3) +#define INT_SDC4_0 (96 + 4) +#define INT_SDC4_1 (96 + 5) +#define INT_PWB_QUP_IN (96 + 6) +#define INT_PWB_QUP_OUT (96 + 7) +#define INT_PWB_QUP_ERR (96 + 8) +/* SCSS_VICFIQSTS3[6:31] are RESERVED */ + +/* Retrofit universal macro names */ +#define INT_ADM_AARM INT_ADM_SC2 +#define INT_USB_HS INT_USB_OTG_HS +#define INT_USB_OTG INT_USB_OTG_HS +#define INT_TCHSCRN1 INT_TSSC_SAMPLE +#define INT_TCHSCRN2 INT_TSSC_PENUP +#define INT_GP_TIMER_EXP INT_GPT0_TIMER_EXP +#define INT_ADSP_A11 INT_AD5A_MPROC_APPS_0 +#define INT_ADSP_A9_A11 INT_AD5A_MPROC_APPS_1 +#define INT_MDDI_EXT INT_EMDH +#define INT_MDDI_PRI INT_PMDH +#define INT_MDDI_CLIENT INT_MDC +#define INT_NAND_WR_ER_DONE INT_EBI2_WR_ER_DONE +#define INT_NAND_OP_DONE INT_EBI2_OP_DONE + +#define NR_MSM_IRQS 128 +#define NR_GPIO_IRQS 182 +#define PMIC8058_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS) +#define NR_PMIC8058_GPIO_IRQS 40 +#define NR_PMIC8058_MPP_IRQS 12 +#define NR_PMIC8058_MISC_IRQS 8 +#define NR_PMIC8058_IRQS (NR_PMIC8058_GPIO_IRQS +\ + NR_PMIC8058_MPP_IRQS +\ + NR_PMIC8058_MISC_IRQS) +#define NR_BOARD_IRQS NR_PMIC8058_IRQS + +#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS) + +#endif /* __ASM_ARCH_MSM_IRQS_7X30_H */ diff --git a/board/qcom/msm7630_surf/msm7630_surf.c b/board/qcom/msm7630_surf/msm7630_surf.c index 95c9f04..9dcf95b 100644 --- a/board/qcom/msm7630_surf/msm7630_surf.c +++ b/board/qcom/msm7630_surf/msm7630_surf.c @@ -30,6 +30,8 @@ #include <asm/arch/proc_comm.h> #include "msm7630_surf.h"
+int critical_section_count; + static struct msm_gpio uart2_gpio_table[] = { { .gpio_cfg = GPIO_CFG(49, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), @@ -61,6 +63,7 @@ void uart2_mux_init(void) #ifdef CONFIG_BOARD_EARLY_INIT_F int board_early_init_f() { + critical_section_count = 0; uart2_mux_init(); uart2_clock_init(); return 0;

Dear Mohamed Haneef,
- Support for msm7630 interrupts
Signed-off-by: Mohamed Haneef mohamed.haneef@lntinfotech.com
arch/arm/cpu/armv7/msm7630/Makefile | 1 + arch/arm/cpu/armv7/msm7630/interrupts.c | 155 +++++++++++++++++++++ arch/arm/include/asm/arch-msm7630/exclusion.h | 42 ++++++ arch/arm/include/asm/arch-msm7630/interrupts.h | 40 ++++++ arch/arm/include/asm/arch-msm7630/irqs.h | 173 ++++++++++++++++++++++++ board/qcom/msm7630_surf/msm7630_surf.c | 3 +
I dont see this file in the tree ... home come? Does this patch depend on some other patchset?
6 files changed, 414 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/armv7/msm7630/interrupts.c create mode 100644 arch/arm/include/asm/arch-msm7630/exclusion.h create mode 100644 arch/arm/include/asm/arch-msm7630/interrupts.h create mode 100644 arch/arm/include/asm/arch-msm7630/irqs.h
diff --git a/arch/arm/cpu/armv7/msm7630/Makefile b/arch/arm/cpu/armv7/msm7630/Makefile index b97026f..b106ddc 100644 --- a/arch/arm/cpu/armv7/msm7630/Makefile +++ b/arch/arm/cpu/armv7/msm7630/Makefile @@ -40,6 +40,7 @@ COBJS-y := board.o COBJS-y += timer.o COBJS-y += acpuclock.o COBJS-y += gpio.o +COBJS-$(CONFIG_USE_IRQ) += interrupts.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS-y)) diff --git a/arch/arm/cpu/armv7/msm7630/interrupts.c b/arch/arm/cpu/armv7/msm7630/interrupts.c new file mode 100644 index 0000000..6cae9c8 --- /dev/null +++ b/arch/arm/cpu/armv7/msm7630/interrupts.c @@ -0,0 +1,155 @@ +/*
- Copyright (c) 2008, Google Inc.
- All rights reserved.
- (C) Copyright 2012
- Larsen & Toubro Infotech Ltd. <www.lntinfotech.com>
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 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.
- Neither the name of Google, Inc. nor the names of its contributors
- may be used to endorse or promote products derived from this
- software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- COPYRIGHT OWNER 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.
DTTO, see my previous response. I'm not sure if we can accept code that's not GPL. Let's see.

* Support for usb gadget device.
Signed-off-by: Mohamed Haneef mohamed.haneef@lntinfotech.com --- arch/arm/include/asm/arch-msm7630/hsusb.h | 182 ++++++++++ drivers/serial/usbtty.h | 2 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/msm_udc.c | 560 +++++++++++++++++++++++++++++ include/configs/msm7630_surf.h | 12 +- include/usb/msm_udc.h | 46 +++ 6 files changed, 800 insertions(+), 3 deletions(-) create mode 100644 arch/arm/include/asm/arch-msm7630/hsusb.h create mode 100644 drivers/usb/gadget/msm_udc.c create mode 100644 include/usb/msm_udc.h
diff --git a/arch/arm/include/asm/arch-msm7630/hsusb.h b/arch/arm/include/asm/arch-msm7630/hsusb.h new file mode 100644 index 0000000..a20f907 --- /dev/null +++ b/arch/arm/include/asm/arch-msm7630/hsusb.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2008, Google Inc. + * All rights reserved. + * + * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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 _HSUSB_H_ +#define _HSUSB_H_ + +#include <asm/arch/iomap.h> + +#ifndef MSM_USB_BASE +#error Must define base address of USB controller MSM_USB_BASE +#endif + +#define USB_ID (MSM_USB_BASE + 0x0000) +#define USB_HWGENERAL (MSM_USB_BASE + 0x0004) +#define USB_HWHOST (MSM_USB_BASE + 0x0008) +#define USB_HWDEVICE (MSM_USB_BASE + 0x000C) +#define USB_HWTXBUF (MSM_USB_BASE + 0x0010) +#define USB_HWRXBUF (MSM_USB_BASE + 0x0014) +#define USB_SBUSCFG (MSM_USB_BASE + 0x0090) + +#define USB_AHB_BURST (MSM_USB_BASE + 0x0090) +#define USB_AHB_MODE (MSM_USB_BASE + 0x0098) +#define USB_CAPLENGTH (MSM_USB_BASE + 0x0100) /* 8 bit */ +#define USB_HCIVERSION (MSM_USB_BASE + 0x0102) /* 16 bit */ +#define USB_HCSPARAMS (MSM_USB_BASE + 0x0104) +#define USB_HCCPARAMS (MSM_USB_BASE + 0x0108) +#define USB_DCIVERSION (MSM_USB_BASE + 0x0120) /* 16 bit */ +#define USB_USBCMD (MSM_USB_BASE + 0x0140) +#define USB_USBSTS (MSM_USB_BASE + 0x0144) +#define USB_USBINTR (MSM_USB_BASE + 0x0148) +#define USB_FRINDEX (MSM_USB_BASE + 0x014C) +#define USB_DEVICEADDR (MSM_USB_BASE + 0x0154) +#define USB_ENDPOINTLISTADDR (MSM_USB_BASE + 0x0158) +#define USB_BURSTSIZE (MSM_USB_BASE + 0x0160) +#define USB_TXFILLTUNING (MSM_USB_BASE + 0x0164) +#define USB_ULPI_VIEWPORT (MSM_USB_BASE + 0x0170) +#define USB_ENDPTNAK (MSM_USB_BASE + 0x0178) +#define USB_ENDPTNAKEN (MSM_USB_BASE + 0x017C) +#define USB_PORTSC (MSM_USB_BASE + 0x0184) +#define USB_OTGSC (MSM_USB_BASE + 0x01A4) +#define USB_USBMODE (MSM_USB_BASE + 0x01A8) +#define USB_ENDPTSETUPSTAT (MSM_USB_BASE + 0x01AC) +#define USB_ENDPTPRIME (MSM_USB_BASE + 0x01B0) +#define USB_ENDPTFLUSH (MSM_USB_BASE + 0x01B4) +#define USB_ENDPTSTAT (MSM_USB_BASE + 0x01B8) +#define USB_ENDPTCOMPLETE (MSM_USB_BASE + 0x01BC) +#define USB_ENDPTCTRL(n) (MSM_USB_BASE + 0x01C0 + (4 * (n))) + +#define USBCMD_RESET 2 +#define USBCMD_ATTACH 1 + +#define USBMODE_DEVICE 2 +#define USBMODE_HOST 3 + + +/* Endpoint Txfer Descriptor dTD as defined by DC */ +struct ept_queue_item { + struct ept_queue_item *next; +#define UDC_DTD_TOTAL_BYTES(info) (((info) >> 16) & 0x7FFF) + unsigned info; /* 30:16-Total Bytes,7:0-Status */ + unsigned page0; + unsigned page1; + unsigned page2; + unsigned page3; + unsigned page4; + unsigned reserved; +}; + +/* Endpoint Queue Head (dQH) as defined by the DC must take up 64K. + * There must be one dQH for every endpoint and direction. */ +struct ept_queue_head { + unsigned config; + unsigned current; /* read-only */ + unsigned next; + unsigned info; + unsigned page0; + unsigned page1; + unsigned page2; + unsigned page3; + unsigned page4; + unsigned reserved_0; + unsigned char setup_data[8]; + unsigned reserved_1; + unsigned reserved_2; + unsigned reserved_3; + unsigned reserved_4; +}; + +#define CONFIG_MAX_PKT(n) ((n) << 16) +#define CONFIG_ZLT (1 << 29) /* stop on zero-len xfer */ +#define CONFIG_IOS (1 << 15) /* IRQ on setup */ + + + +#define TERMINATE 1 + +#define INFO_BYTES(n) ((n) << 16) +#define INFO_IOC (1 << 15) +#define INFO_ACTIVE (1 << 7) +#define INFO_HALTED (1 << 6) +#define INFO_BUFFER_ERROR (1 << 5) +#define INFO_TX_ERROR (1 << 3) + +#define STS_NAKI (1 << 16) /* */ +#define STS_SLI (1 << 8) /* R/WC - suspend state entered */ +#define STS_SRI (1 << 7) /* R/WC - SOF recv'd */ +#define STS_URI (1 << 6) /* R/WC - RESET recv'd - write to clear */ +#define STS_FRI (1 << 3) /* R/WC - Frame List Rollover */ +#define STS_PCI (1 << 2) /* R/WC - Port Change Detect */ +#define STS_UEI (1 << 1) /* R/WC - USB Error */ +#define STS_UI (1 << 0) /* R/WC - USB Transaction Complete */ + +/* bits used in all the endpoint status registers */ +#define EPT_TX(n) (1 << ((n) + 16)) +#define EPT_RX(n) (1 << (n)) + + +#define CTRL_TXE (1 << 23) /* TX Endpoint Enable */ +#define CTRL_TXR (1 << 22) /* TX Data Toggle Reset */ +#define CTRL_TXI (1 << 21) /* TX Data Toggle Inhibit */ +#define CTRL_TXT(n) ((n) << 18) /* TX Endpoint Type */ +#define CTRL_TXD (1 << 17) /* TX Endpoint Data Source */ +#define CTRL_TXS (1 << 16) /* TX Endpoint Stall */ +#define CTRL_RXE (1 << 7) /* RX Endpoint Enable */ +#define CTRL_RXR (1 << 6) /* RX Data Toggle Reset */ +#define CTRL_RXI (1 << 5) /* RX Data Toggle Inhibit */ +#define CTRL_RXT(n) ((n) << 2) /* RX Endpoint Type */ +#define CTRL_RXD (1 << 1) /* RX Endpoint Data Source */ +#define CTRL_RXS (1 << 0) /* RX Endpint Stall */ + +#define CTRL_TXT_CTRL (0 << 18) +#define CTRL_TXT_ISOCH (1 << 18) +#define CTRL_TXT_BULK (2 << 18) +#define CTRL_TXT_INT (3 << 18) + +#define CTRL_RXT_CTRL (0 << 2) +#define CTRL_RXT_ISOCH (1 << 2) +#define CTRL_RXT_BULK (2 << 2) +#define CTRL_RXT_INT (3 << 2) + +#define ULPI_WAKEUP (1 << 31) +#define ULPI_RUN (1 << 30) +#define ULPI_WRITE (1 << 29) +#define ULPI_READ (0 << 29) +#define ULPI_STATE_NORMAL (1 << 27) +#define ULPI_ADDR(n) (((n) & 255) << 16) +#define ULPI_DATA(n) ((n) & 255) +#define ULPI_DATA_READ(n) (((n) >> 8) & 255) +#define PORTSC_PTC (0xF << 16) +#define PORTSC_PTC_TST_PKT (0x4 << 16) + + +#endif diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h index e449cd7..8321447 100644 --- a/drivers/serial/usbtty.h +++ b/drivers/serial/usbtty.h @@ -35,6 +35,8 @@ #include <usb/pxa27x_udc.h> #elif defined(CONFIG_SPEAR3XX) || defined(CONFIG_SPEAR600) #include <usb/spr_udc.h> +#elif defined(CONFIG_MSM_UDC) +#include <usb/msm_udc.h> #endif
#include <version.h> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 64b091f..44ffa8a 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -44,6 +44,7 @@ COBJS-$(CONFIG_OMAP1610) += omap1510_udc.o COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o COBJS-$(CONFIG_CPU_PXA27X) += pxa27x_udc.o COBJS-$(CONFIG_SPEARUDC) += spr_udc.o +COBJS-$(CONFIG_MSM_UDC) += msm_udc.o endif endif
diff --git a/drivers/usb/gadget/msm_udc.c b/drivers/usb/gadget/msm_udc.c new file mode 100644 index 0000000..7c2a14a --- /dev/null +++ b/drivers/usb/gadget/msm_udc.c @@ -0,0 +1,560 @@ +/* + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <asm/io.h> +#include <malloc.h> +#include <usbdevice.h> +#include <usb/msm_udc.h> +#include <asm/arch/hsusb.h> +#include <asm/arch/irqs.h> +#include <asm/arch/exclusion.h> +#include <asm/arch/interrupts.h> +#include "ep0.h" + +#define mdelay(ms) udelay((ms) * 1000) +#define USB_EP_NUM(ep) ((ep)->endpoint_address & USB_ENDPOINT_NUMBER_MASK) +#define USB_EP_DIR(ep) ((ep)->endpoint_address & USB_ENDPOINT_DIR_MASK) +#define USB_EP_MAX_PKT(ep) (USB_EP_DIR(ep) ? (ep)->tx_packetSize : \ + (ep)->rcv_packetSize) +#ifdef DEBUG +/* Debug output must not use stdout as that can cause an infinite loop when + * stdout is usbtty */ +#define udcdbg serial_printf +#else +#define udcdbg(fmt, args...) +#endif + +static struct ept_queue_head *dQHs; +static int usb_highspeed; /* Binary value indicating supported speed */ +static struct usb_device_instance *udc_device; +volatile static struct ept_queue_item *dTD_list[USB_MAX_EPTS]; + +static struct urb *msm_udc_get_urb_by_dir(unsigned num, unsigned direction) +{ + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + struct urb **urb = (direction == USB_DIR_IN) ? &epi->tx_urb : + &epi->rcv_urb; + + if (!*urb) { + *urb = usbd_alloc_urb(udc_device, epi); + udcdbg("ep%i%s allocating new URB %#08x\n", num, + USB_EP_DIR(epi) ? "in" : "out", (unsigned) *urb); + } + + return *urb; +} + +static struct urb *msm_udc_get_urb(unsigned num) +{ + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + return msm_udc_get_urb_by_dir(num, USB_EP_DIR(epi)); +} + +/** + * Returns the dQH from the list + * @param num 0..15 where 0 is the control endpoint + * @param direction = [USB_DIR_IN, USB_DIR_OUT] + */ +static struct ept_queue_head *msm_udc_get_dQH(unsigned num, unsigned direction) +{ + /* Even elements of dQHs are for RX and odd for TX */ + return (struct ept_queue_head *) (dQHs + (num * 2) + + ((direction == USB_DIR_IN) ? 1 : 0)); +} + +static void msm_udc_ep_enable(unsigned num, unsigned enable) +{ + unsigned n = readl(USB_ENDPTCTRL(num)); + + if (enable) { + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + unsigned direction = USB_EP_DIR(epi); + + if (direction == USB_DIR_IN) + n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); + else + n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); + + if (num != 0) { + struct ept_queue_head *dQH = + msm_udc_get_dQH(num, direction); + unsigned highspeed = + (((readl(USB_PORTSC) >> 26) & 3) == 2) ? 1 : 0; + unsigned max_packet = highspeed ? 512 : 64; + /* The Mult field is 0 for all but isochronous EPs */ + dQH->config = CONFIG_MAX_PKT(max_packet) | CONFIG_ZLT; + } + } + writel(n, USB_ENDPTCTRL(num)); +} + +static void msm_udc_ep0_send_ack(void) +{ + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[0]; + struct urb *urb; + + /* Send ACK in opposite direction to request */ + epi->endpoint_address = USB_EP_DIR(epi) ? USB_DIR_OUT : USB_DIR_IN; + urb = msm_udc_get_urb(0); + urb->actual_length = 0; + udc_endpoint_write(epi); +} + +#define SETUP(type, request) (((type) << 8) | (request)) +static void msm_udc_handle_setup(void) +{ + int err; + struct usb_device_request s; + struct ept_queue_head *dQH = msm_udc_get_dQH(0, USB_DIR_OUT); + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[0]; + struct urb *urb; + + /* Setup Packet Handling (if Setup Lockout is used): + * - Backup dQH.SsetupBuffer + * - Write a 1 to USB_ENDPTSETUPSTAT which deactivates Setup Lockout + * - Process the packet using the copy (flush/dealloc stale handshake + * phases) + * - Before priming for handshake phase, wait for ENDPTSETUPSTAT to + * transition to zero */ + memcpy(&s, dQH->setup_data, sizeof(struct usb_device_request)); + writel(EPT_RX(0), USB_ENDPTSETUPSTAT); + + epi->endpoint_address = s.bmRequestType & USB_REQ_DIRECTION_MASK; + urb = msm_udc_get_urb(0); /* URB is dependent on EP direction */ + urb->device_request = s; + + print_usb_device_request(&s); + + /* Handle gadget internals and for IN requests setup urb */ + err = ep0_recv_setup(urb); + if (err) + return; + + switch (SETUP(s.bmRequestType, s.bRequest)) { + case SETUP(USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_CONFIGURATION): + udcdbg("set config\n"); + if (s.wValue == 1) { /* Online */ + unsigned i; + for (i = 1; i < udc_device->bus->max_endpoints; i++) + msm_udc_ep_enable(i, s.wValue); + usbd_device_event_irq(udc_device, + DEVICE_CONFIGURED, 0); + } else { /* Offline */ + writel(0, USB_ENDPTCTRL(1)); + usbd_device_event_irq(udc_device, + DEVICE_DE_CONFIGURED, 0); + } + msm_udc_ep0_send_ack(); + break; + case SETUP(USB_REQ_RECIPIENT_ENDPOINT, USB_REQ_CLEAR_FEATURE): + udcdbg("clear feature\n"); + if ((s.wValue == 0) && (s.wLength == 0)) { + unsigned num = s.wIndex & USB_ENDPOINT_NUMBER_MASK; + unsigned direction = s.wIndex & USB_ENDPOINT_DIR_MASK; + + udcdbg("Clear feature ep%i%s\n", num, direction ? + "in" : "out"); + msm_udc_ep_enable(num, 1); + msm_udc_ep0_send_ack(); + } else { + err = -1; /* stall */ + } + break; + case SETUP(USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_ADDRESS): + udcdbg("set address\n"); + writel((s.wValue << 25) | (1 << 24), USB_DEVICEADDR); + usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0); + msm_udc_ep0_send_ack(); + break; + case SETUP(USB_REQ_RECIPIENT_INTERFACE, USB_REQ_SET_INTERFACE): + udcdbg("set interface\n"); + err = -1; /* stall */ + break; + case SETUP(USB_REQ_RECIPIENT_DEVICE, USB_REQ_SET_FEATURE): + udcdbg("set feature\n"); + if (s.wIndex == 0x400) { + udcdbg("Entering test mode for TST_PKT\n"); + unsigned mode = readl(USB_PORTSC) & (~PORTSC_PTC); + writel(mode | PORTSC_PTC_TST_PKT, USB_PORTSC); + } + msm_udc_ep0_send_ack(); + break; + } + + if (!err) { + if ((s.bmRequestType & USB_REQ_DIRECTION_MASK) == + USB_REQ_DEVICE2HOST) + udc_endpoint_write(epi); /* Request returns data */ + /* else we already sent ACK as needed */ + } else { + udcdbg("STALL\n"); + writel((1<<16) | (1 << 0), USB_ENDPTCTRL(0)); + } +} + +static void msm_udc_ep_complete(unsigned num, unsigned direction) +{ + struct ept_queue_item *dTD = dTD_list[num]; + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + struct urb *urb = msm_udc_get_urb_by_dir(num, direction); + unsigned left; + unsigned actual; /* urb->actual_length modified by _complete() */ + int urb_bad = 0; + + udcdbg("ep%i%s complete dTD=%p ", num, direction ? "in" : "out", dTD); + if (dTD_list[num] == NULL) { + udcdbg("FAIL no xfer has been queued\n"); + return; + } else if (dTD->info & INFO_ACTIVE) { + udcdbg("BAIL transfer descriptor is active\n"); + return; + } else if (dTD_list[num]->next == (struct ept_queue_item *) TERMINATE) + dTD_list[num] = NULL; + else { + udcdbg("popping dTD "); + dTD_list[num] = dTD_list[num]->next; + } + + left = UDC_DTD_TOTAL_BYTES(dTD->info); + actual = ((num != 0) && (direction == USB_DIR_OUT)) ? + urb->buffer_length : urb->actual_length; + epi->last = actual - left; + + if (dTD->info & (INFO_HALTED | INFO_BUFFER_ERROR | INFO_TX_ERROR)) { + udcdbg("FAIL info=%x,page0=%x\n", dTD->info, dTD->page0); + urb_bad = 1; + } else + udcdbg("SUCCESS left=%i,sent=%i,last=%i,len=%i\n", left, + epi->sent, epi->last, urb->actual_length); + + if (direction == USB_DIR_OUT) + usbd_rcv_complete(epi, epi->last, urb_bad); + else + usbd_tx_complete(epi); + + if (!urb_bad && (num == 0) && (actual != 0)) + msm_udc_ep0_send_ack(); + free(dTD); +} + +static void msm_udc_handle_usbsts(unsigned status) +{ + if (status & STS_SLI) { + udcdbg("STS_SLI = Suspend\n"); + /* Could keep track and subsequently use Resume signalling but + * this is optional */ + } + if (status & STS_URI) { + unsigned num; + udcdbg("STS_URI = Reset\n"); + /* Clear setup token semaphores */ + writel(readl(USB_ENDPTSETUPSTAT), USB_ENDPTSETUPSTAT); + /* Clear endpoint complete status bits */ + writel(readl(USB_ENDPTCOMPLETE), USB_ENDPTCOMPLETE); + writel(0xffffffff, USB_ENDPTFLUSH); + /* After reset, all EPs but ep0 are uninit and disabled */ + writel(0, USB_ENDPTCTRL(1)); + /* error out any pending reqs */ + for (num = 0; num < udc_device->bus->max_endpoints; num++) { + while (dTD_list[num] != NULL) { + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + dTD_list[num]->info = INFO_HALTED; + msm_udc_ep_complete(num, USB_EP_DIR(epi)); + } + } + } + if (status & STS_PCI) { + /* Comes after a Reset to indicate the transition into the + * Default state and comes as part of the Reset process. The + * device speed can now be read out of PORTSC */ + usb_highspeed = (((readl(USB_PORTSC) >> 26) & 3) == 2) ? 1 : 0; + udcdbg("STS_PCI = Port Change Detect HS=%i\n", usb_highspeed); + usbd_device_event_irq(udc_device, DEVICE_RESET, 0); + } + if ((status & STS_UI) || (status & STS_UEI)) { + unsigned n, num; + /* USB Interrupt and USB Error Interrupt */ + udcdbg("STS_UI and STS_UEI = TX(s) Done\n"); + if (status & STS_UEI) + udcdbg("Error %#x\n", readl(USB_ENDPTCOMPLETE)); + + n = readl(USB_ENDPTSETUPSTAT); + if (n & EPT_RX(0)) /* Handle setup first */ + msm_udc_handle_setup(); + + n = readl(USB_ENDPTCOMPLETE); + writel(n, USB_ENDPTCOMPLETE); + udcdbg("USB_ENDPTCOMPLETE = %#x\n", n); + for (num = 0; num < udc_device->bus->max_endpoints; num++) { + if (EPT_TX(num) & n) + msm_udc_ep_complete(num, USB_DIR_IN); + if (EPT_RX(num) & n) + msm_udc_ep_complete(num, USB_DIR_OUT); + } + } +} + +static enum handler_return msm_udc_interrupt_handler(void *arg) +{ + unsigned sts = readl(USB_USBSTS); + writel(sts, USB_USBSTS); + sts &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); + + udcdbg("\nmsm_udc_interrupt_handler(USBSTS=%#0x):\n", sts); + + while (sts != 0) { + msm_udc_handle_usbsts(sts); + + sts = readl(USB_USBSTS); + writel(sts, USB_USBSTS); + sts &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); + udcdbg("USBSTS = %#x\n", sts); + } + + return INT_RESCHEDULE; +} + +int udc_endpoint_write(struct usb_endpoint_instance *epi) +{ + unsigned num = USB_EP_NUM(epi); + unsigned direction = USB_EP_DIR(epi); + struct urb *urb = msm_udc_get_urb(num); + struct ept_queue_head *dQH = msm_udc_get_dQH(num, direction); + struct ept_queue_item *dTD = memalign(sizeof(*dTD), sizeof(*dTD)); + unsigned length = ((num == 0) | (direction == USB_DIR_IN)) ? + urb->actual_length : urb->buffer_length; + + udcdbg("ep%i%sWrite buffer=%p,length=%i,actual_length=%i,dTD=%p", + num, direction ? "in" : "out", urb->buffer, length, + urb->actual_length, dTD); + + if (length > 0x4000) + return -1; + + epi->sent = 0; + /* From 6.6.2 Building a Transfer Descriptor: + * 1. Initialize first 7 DWords to 0. + * 2. Set the terminate bit to 1 + * 3. Fill in total bytes with transfer size. + * 4. Set the interrupt on complete if desired. + * 5. Initialize the status field with the active bit set to 1 and + * all remaining status bits set to 0 + * 6. Fill in buffer pointer page 0 and the current offset to + * point to the start of the data buffer. + * 7. Initialize buffer pointer page 1 through page 4 to be one + * greater than each of the previous buffer pointer. */ + memset(dTD, 0, sizeof(*dTD)); + dTD->next = (struct ept_queue_item *) TERMINATE; + dTD->info = INFO_BYTES(length) | INFO_IOC | INFO_ACTIVE; + dTD->page0 = (unsigned) urb->buffer; + dTD->page1 = ((unsigned) urb->buffer & 0xfffff000) + 0x1000; + dTD->page2 = ((unsigned) urb->buffer & 0xfffff000) + 0x2000; + dTD->page3 = ((unsigned) urb->buffer & 0xfffff000) + 0x3000; + + /* To Prime: + * 1. Fetch the dTD for the transaction pointed to by dQH + * 2. Store the dTD in the dQH + * 3. Indicate primed in ENDPTPRIME */ + enter_critical_section(); + /* Handle the case where there are completed dTDs waiting */ + if (dTD_list[num] != NULL) { + struct ept_queue_item *dTDlast = dTD_list[num]; + unsigned qDepth = 1; + while (dTDlast->next != (struct ept_queue_item *) TERMINATE) { + dTDlast = dTDlast->next; + qDepth++; + } + udcdbg(",qing size=%i", qDepth); + dTDlast->next = dTD; + } else /* dQH only references active and queued dTDs */ + dTD_list[num] = dTD; + if ((dQH->next != TERMINATE) && (dQH->next != 0)) + udcdbg(",dQH busy\n"); + else { + int bit = direction ? EPT_TX(num) : EPT_RX(num); + dQH->next = (unsigned) dTD; + dQH->info = 0; + udcdbg(",bit=%x,dQH=%p\n", bit, dQH); + writel(bit, USB_ENDPTPRIME); + } + exit_critical_section(); + + return 0; +} + +void udc_irq(void) /* Handle any USB events */ +{ + unsigned num; + unsigned waited = 0; + /* OUT endpoints must be primed to receive data from the host */ + if (udc_device && (udc_device->device_state == STATE_CONFIGURED)) { + for (num = 1; num < udc_device->bus->max_endpoints; num++) { + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + if ((USB_EP_DIR(epi) == USB_DIR_OUT) && + (dTD_list[num] == NULL)) { + struct urb *urb = msm_udc_get_urb(num); + + if (urb->actual_length == 0) + udc_endpoint_write(epi); + } + } + } + /* Actual packet processing handled in IRQs */ + /* Delay the main thread so only one TX can be queued at a tuime */ + for (num = 0; num < udc_device->bus->max_endpoints; num++) { + struct usb_endpoint_instance *epi = + &udc_device->bus->endpoint_array[num]; + if ((USB_EP_DIR(epi) == USB_DIR_IN) && + (dTD_list[num] != NULL)) { + udcdbg("Waiting on epIn dTD_list[%i]=%p\n", num, + dTD_list[num]); + waited = 1; + while (dTD_list[num] != NULL) + /* Wait for interrupt to run */; + num = 0; /* Reset loop */ + } + } + if (waited) + udcdbg("Done waiting\n"); +} + +void udc_set_nak(int epid) +{ + /* TODO */ +} + +void udc_unset_nak(int epid) +{ + /* TODO */ +} + +void udc_disconnect(void) +{ + udcdbg("Disconnect USB\n"); + writel(0, USB_USBINTR); + mask_interrupt(INT_USB_HS); + writel(0x00080000, USB_USBCMD); /* disable pullup */ + mdelay(10); +} + +void udc_connect(void) +{ + udcdbg("Connect USB\n"); + /* Enable the Run/Stop bit (D+ pullup enable): this initiates a restart + * that the DCD must monitor for. ep0 q heads must be setup */ + writel(0x00080001, USB_USBCMD); + usbd_device_event_irq(udc_device, DEVICE_HUB_CONFIGURED, 0); + /* Setup interrupts to handle incoming RESET on the bus */ + enter_critical_section(); + register_int_handler(INT_USB_HS, msm_udc_interrupt_handler, NULL); + writel(STS_URI | STS_SLI | STS_UI | STS_PCI, USB_USBINTR); + unmask_interrupt(INT_USB_HS); + exit_critical_section(); +} + +void udc_startup_events(struct usb_device_instance *device) +{ + udcdbg("Startup events\n"); + usbd_device_event_irq(device, DEVICE_INIT, 0); + usbd_device_event_irq(device, DEVICE_CREATE, 0); + udc_device = device; +} + +void udc_setup_ep(struct usb_device_instance *device, + unsigned int num, struct usb_endpoint_instance *epi) +{ + unsigned direction = USB_EP_DIR(epi); + struct ept_queue_head *dQH; + int cfg = CONFIG_MAX_PKT(USB_EP_MAX_PKT(epi)) | CONFIG_ZLT; + + if (num >= USB_MAX_EPTS) { + udcdbg("ERROR DC only supports %i endpoints!\n", USB_MAX_EPTS); + return; + } + + udcdbg("Init ep%i%s max=%i,", num, direction ? "in" : "out", + USB_EP_MAX_PKT(epi)); + + if (num == 0) { + /* For EP0 both directions must be setup */ + direction = USB_DIR_IN; + dQH = msm_udc_get_dQH(num, direction); + udcdbg("dQH0in=%#08x,", (unsigned) dQH); + dQH->config = cfg; + direction = USB_DIR_OUT; + cfg |= CONFIG_IOS; + } + dQH = msm_udc_get_dQH(num, direction); + udcdbg("dQH%i%s=%#08x\n", num, direction ? "in" : "out", + (unsigned) dQH); + dQH->config = cfg; +} + +int udc_init(void) +{ + hsusb_clock_init(); + writel(0x81000000, USB_PORTSC); /* select ULPI phy */ + + udcdbg("udc_init():Read USB_ID %#010x from %#010x\n", + readl(USB_ID), USB_ID); + + /* Init globals */ + dQHs = NULL; + usb_highspeed = 0; + udc_device = NULL; + memset(dTD_list, 0, sizeof(dTD_list)); + + /* Reset */ + writel(0x00080002, USB_USBCMD); + mdelay(20); + + writel(0, USB_AHB_MODE); + writel(0, USB_AHB_BURST); + + /* According to the CI13611 Programmers Guide, the software must ensure + * that no interface data-structure reachable by the Device Controller + * spans a 4K page boundary */ + dQHs = memalign(4096, 4096); + if (dQHs == NULL) + return -1; + memset(dQHs, 0, 4096); + /* ENDPOINTLISTADDR must point to a contiguous chunk of memory where + * the even numbered addresses are RX endpoints and odd TX endpoints. + * The UDC indexes into this list based on the endpoint number. + * Eg. Offset Queue-Head + * 0 0 - Out + * 4 0 - In + * 8 1 - Out + * etc. etc. */ + writel((unsigned) dQHs, USB_ENDPOINTLISTADDR); + writel(0x02, USB_USBMODE); /* select DEVICE mode */ + writel(0xffffffff, USB_ENDPTFLUSH); + mdelay(20); + return 0; +} diff --git a/include/configs/msm7630_surf.h b/include/configs/msm7630_surf.h index 5aa6be0..e334a6f 100644 --- a/include/configs/msm7630_surf.h +++ b/include/configs/msm7630_surf.h @@ -36,8 +36,12 @@ /* * Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (4 * 1024) /* 4KB */ -#define CONFIG_MSM7630 +#define CONFIG_SYS_MALLOC_LEN (4 * 1024) /* 4KB */ + +/* Enable USB */ +#define CONFIG_MSM_UDC +#define CONFIG_USB_TTY +#define CONFIG_USB_DEVICE
/* * select serial console configuration @@ -62,8 +66,9 @@ #undef CONFIG_SYS_MAX_FLASH_SECT #define CONFIG_EXTRA_ENV_SETTINGS \ "console=ttyS0,115200n8\0" \ + "usbtty=cdc_acm\0"
-#define CONFIG_BOOTDELAY 2 /* -1 to disable auto boot */ +#define CONFIG_BOOTDELAY -1 /* -1 to disable auto boot */
/* * Miscellaneous configurable options @@ -101,6 +106,7 @@ * IRQ Settings */
+#define CONFIG_USE_IRQ #define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ #define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
diff --git a/include/usb/msm_udc.h b/include/usb/msm_udc.h new file mode 100644 index 0000000..c8b09c6 --- /dev/null +++ b/include/usb/msm_udc.h @@ -0,0 +1,46 @@ +/* + * (C) Copyright 2012 + * Larsen & Toubro Infotech Ltd. <www.lntinfotech.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <usbdevice.h> + +#define USB_MAX_EPTS 16 + +/* Define the EP number and packet sizes */ +#define EP0_MAX_PACKET_SIZE 64 +#define UDC_INT_ENDPOINT 1 +#define UDC_INT_PACKET_SIZE 64 +#define UDC_OUT_ENDPOINT 2 +#define UDC_OUT_PACKET_SIZE 512 +#define UDC_IN_ENDPOINT 3 +#define UDC_IN_PACKET_SIZE 512 +#define UDC_BULK_PACKET_SIZE 512 + +extern void hsusb_clock_init(void); + +int udc_endpoint_write(struct usb_endpoint_instance *endpoint); +void udc_irq(void); +void udc_set_nak(int epid); +void udc_unset_nak(int epid); +void udc_disconnect(void); +void udc_connect(void); +void udc_startup_events(struct usb_device_instance *device); +void udc_setup_ep(struct usb_device_instance *device, + unsigned int epid, struct usb_endpoint_instance *ep); +int udc_init(void);

* enabling high capacity eMMC cards.
Signed-off-by: Mohamed Haneef mohamed.haneef@lntinfotech.com --- board/qcom/msm7630_surf/msm7630_surf.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/board/qcom/msm7630_surf/msm7630_surf.c b/board/qcom/msm7630_surf/msm7630_surf.c index 9dcf95b..9ca6843 100644 --- a/board/qcom/msm7630_surf/msm7630_surf.c +++ b/board/qcom/msm7630_surf/msm7630_surf.c @@ -147,7 +147,7 @@ int board_mmc_init(bd_t *bis) mmc_2->init = qc_board_mmc_init; mmc_2->voltages = MMC_VDD_29_30|MMC_VDD_165_195; mmc_2->host_caps = MMC_MODE_4BIT|MMC_MODE_HS|MMC_MODE_8BIT| - MMC_MODE_HS_52MHz; + MMC_MODE_HS_52MHz|MMC_MODE_HC; mmc_2->f_min = MMC_CLK_400KHZ; mmc_2->f_max = MMC_CLK_48MHZ; sprintf(mmc_2->name, "Internal_Card");
participants (2)
-
Marek Vasut
-
Mohamed Haneef