diff options
Diffstat (limited to 'drivers/otg/hardware/mxc-ocd.c')
-rw-r--r-- | drivers/otg/hardware/mxc-ocd.c | 692 |
1 files changed, 692 insertions, 0 deletions
diff --git a/drivers/otg/hardware/mxc-ocd.c b/drivers/otg/hardware/mxc-ocd.c new file mode 100644 index 000000000000..16636c22eff2 --- /dev/null +++ b/drivers/otg/hardware/mxc-ocd.c @@ -0,0 +1,692 @@ +/* + * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +/* + * otg/hardware/mxc-ocd.c -- USB Device Controller driver + * @(#) sl@belcarra.com/whiskey.enposte.net|otg/platform/mxc/mxc-ocd.c|20070612233038|32668 + * + * Copyright (c) 2004-2005 Belcarra + * Copyright (c) 2005-2007 Belcarra Technologies 2005 Corp + * + * By: + * Stuart Lynne <sl@lbelcarra.com>, + * Bruce Balden <balden@belcarra.com> + * + */ +/*! + * @file otg/hardware/mxc-ocd.c + * @brief Freescale USB OTG Controller Driver + * + * This is the OTG Controller Driver. It does generic configuration + * and handles the all USBOTG interrupts. + * + * There is no board or platform level code here. + * + * @ingroup FSOTG + * @ingroup OCD + * + */ + +#include <otg/pcd-include.h> +#include "mxc-lnx.h" +#include "mxc-hardware.h" + +int mxc_transceiver_mode; + +/* ********************************************************************************************* */ +#define TIMEOUT_VALUE 1000 +/*! + * mxc_func_clock_on() - enable function controller clock + */ +void mxc_func_clock_on(void) +{ + u32 timeout = TIMEOUT_VALUE; + fs_orl(OTG_CORE_CLK_CTRL, MODULE_FUNC_CLK); + while(!( fs_rl(OTG_CORE_CLK_CTRL) & MODULE_FUNC_CLK)) { timeout--; if (!timeout) break; } + + //TRACE_MSG1(OCD, "FUNC CLOCK ON: %08x", fs_rl(OTG_CORE_CLK_CTRL)); + + //fs_orl(OTG_CORE_CINT_STEN, MODULE_ASFCINT_EN |MODULE_FCINT_EN); +} + +/*! + * mxc_host_clock_on() - enable host controller clock + */ +void mxc_host_clock_on(void) +{ + u32 timeout = TIMEOUT_VALUE; + fs_orl(OTG_CORE_CLK_CTRL, MODULE_HOST_CLK); + while(!( fs_rl(OTG_CORE_CLK_CTRL) & MODULE_HOST_CLK)) { timeout--; if (!timeout) break; } + //TRACE_MSG1(OCD, "HOST CLOCK ON: %08x", fs_rl(OTG_CORE_CLK_CTRL)); +} + +/*! + * mxc_func_clock_off() - disable function controller clock + */ +void mxc_func_clock_off(void) +{ + u32 timeout = TIMEOUT_VALUE; + fs_andl(OTG_CORE_CLK_CTRL, 0x0); + while((fs_rl(OTG_CORE_CLK_CTRL) & (MODULE_FUNC_CLK | MODULE_MAIN_CLK))) { timeout--; if (!timeout) break; } + //TRACE_MSG1(OCD, "FUNC CLOCK OFF: %08x", fs_rl(OTG_CORE_CLK_CTRL)); +} + +/*! + * mxc_host_clock_off() - disable host controller clock + */ +void mxc_host_clock_off(void) +{ + u32 timeout = TIMEOUT_VALUE; + fs_andl(OTG_CORE_CLK_CTRL, 0x0); + while((fs_rl(OTG_CORE_CLK_CTRL) & (MODULE_HOST_CLK | MODULE_MAIN_CLK))) { timeout--; if (!timeout) break; } + //TRACE_MSG1(OCD, "HOST CLOCK OFF: %08x", fs_rl(OTG_CORE_CLK_CTRL)); +} + +/*! + * mxc_main_clock_on() - enable main clock + */ +void mxc_main_clock_on(void) +{ + u32 timeout = TIMEOUT_VALUE; + fs_orl(OTG_CORE_CLK_CTRL, MODULE_MAIN_CLK); + while(!( fs_rl(OTG_CORE_CLK_CTRL) & MODULE_MAIN_CLK)) { timeout--; if (!timeout) break; } + //TRACE_MSG1(OCD, "MAIN CLOCK ON: %08x", fs_rl(OTG_CORE_CLK_CTRL)); +} + +/*! + * mxc_main_clock_off() - disable main clock + */ +void mxc_main_clock_off(void) +{ + u32 timeout = TIMEOUT_VALUE; + //fs_wl_set(OCD, OTG_CORE_CLK_CTRL, 0); + fs_wl(OTG_CORE_CLK_CTRL, 0); + while((fs_rl(OTG_CORE_CLK_CTRL) & MODULE_MAIN_CLK)) { timeout--; if (!timeout) break; } + //TRACE_MSG1(OCD, "MAIN CLOCK OFF: %08x", fs_rl(OTG_CORE_CLK_CTRL)); +} + +/*! + * mxc_set_transceiver_mode(int) + * @param mode - mode to set + */ +void mxc_set_transceiver_mode(int mode) +{ + mxc_transceiver_mode = mode; + fs_andl(OTG_CORE_HWMODE, ~0xf0); + fs_orl(OTG_CORE_HWMODE, (mode << 6) | (mode << 4)); // set to software hnp + //TRACE_MSG2(OCD, "set hwmode: %08x want %08x", fs_rl(OTG_CORE_HWMODE), (mode << 6) | (mode << 4)); + //TRACE_MSG1(OCD, "hwmode: %08x", fs_rl(OTG_CORE_HWMODE)); +} + + + +/* ********************************************************************************************* */ + +/*! + * mxc_disable_interrupts() - disable interrupts + */ +void mxc_disable_interrupts (void) +{ + fs_wl(OTG_CORE_CINT_STEN, 0 ); + fs_wl(OTG_CORE_HINT_STEN, 0 ); + fs_wl(OTG_HOST_SINT_STEN, 0 ); + fs_wl(OTG_HOST_XYINT_STEN, 0 ); + fs_wl(OTG_HOST_ETD_EN, 0); + fs_wl(OTG_HOST_ETD_DONE, 0 ); + fs_wl(OTG_FUNC_SINT_STEN, 0 ); + fs_wl(OTG_FUNC_XYINT_STEN, 0 ); + fs_wl(OTG_FUNC_EP_EN, 0 ); + fs_wl(OTG_FUNC_EP_DEN, 0 ); +} + +/* ********************************************************************************************* */ + +/* ********************************************************************************************* */ +/*! + * mxc_init() - initial tcd setup + * Allocate interrupts and setup hardware. + * @param otg - otg instance + */ +void mxc_init (struct otg_instance *otg) +{ + int timeout; + unsigned long flags; + //u32 mode = XCVR_D_SE0; + u32 mode = XCVR_SE0_D_NEW; + + TRACE_MSG0(otg->ocd->TAG, "FS_INIT"); + local_irq_save (flags); + + fs_wl(OTG_SYS_CTRL, 0x0); + + /* 2. Ensure hardware is reset and cleared + */ + // XXX + //fs_clear_words((volatile u32 *)IO_ADDRESS(OTG_DMA_BASE), (32*16/4)); + fs_clear_words((volatile u32 *)IO_ADDRESS(OTG_DMA_BASE), (16*16/4)); + fs_clear_words((void *)IO_ADDRESS(OTG_FUNC_BASE), 0x200); + mxc_main_clock_off(); + + //fs_wl_set(OCD, OTG_CORE_RST_CTRL, MODULE_RSTI2C | 0x3f); + fs_wl(OTG_CORE_RST_CTRL, MODULE_RSTI2C | 0x3f); + while (fs_rl(OTG_CORE_RST_CTRL)); + + /* 3. OTG Hardware Mode and clocks + * set to diff, diff and Configure the OTG to behave as function + */ + TRACE_MSG0(otg->ocd->TAG, "3. OTG Software Mode and clock"); + + fs_orl(OTG_CORE_HWMODE, MODULE_CRECFG_SHNP); // set to software hnp + mxc_set_transceiver_mode(mxc_transceiver_mode); + TRACE_MSG2(otg->ocd->TAG, "FS_INIT: set hwmode: %08x want %08x", fs_rl(OTG_CORE_HWMODE), MODULE_CRECFG_SHNP); + + fs_andl(OTG_CORE_HNP_CSTAT, ~0x00000800); + fs_rl(OTG_CORE_HNP_CSTAT); + + //fs_wl_set(OCD, OTG_CORE_HNP_T3PCR, 0x00000000); + fs_wl(OTG_CORE_HNP_T3PCR, 0x00000000); + fs_rl(OTG_CORE_HNP_T3PCR); + + TRACE_MSG0(otg->ocd->TAG, "6. Enable "); + TRACE_MSG0(otg->ocd->TAG, "enable core interrupts"); + + fs_wl(OTG_CORE_CINT_STEN, 0); + + fs_wl(OTG_CORE_CINT_STEN, MODULE_ASHNPINT_EN | + MODULE_ASHCINT_EN | MODULE_HNPINT_EN | MODULE_FCINT | MODULE_HCINT); + + + TRACE_MSG0(otg->ocd->TAG, "enable host interrupts"); + fs_wl(OTG_CORE_HINT_STEN, HNP_I2COTGINT_EN | HNP_AWAITBTO_EN | + HNP_AIDLEBDTO_EN | HNP_SRPSUCFAIL_EN | HNP_SRPINT_EN | HNP_VBUSERROR_EN | + HNP_ABSEVAILD_EN | HNP_ABUSVALID_EN | HNP_MASSLVCHG_EN | HNP_IDCHANGE_EN); + + TRACE_MSG0(otg->ocd->TAG, "disable various host interrupts"); + fs_wl(OTG_HOST_XYINT_STEN, 0); + fs_wl(OTG_HOST_ETD_EN, 0); + fs_wl(OTG_HOST_ETD_DONE, 0); + fs_wl(OTG_HOST_SINT_STEN, 0); + + TRACE_MSG0(otg->ocd->TAG, "disable various function interrupts"); + fs_wl(OTG_FUNC_XYINT_STEN, 0); + fs_wl(OTG_FUNC_EP_EN, 0); + fs_wl(OTG_FUNC_EP_DEN, 0); + + fs_wl(OTG_DMA_DINT_STEN, 0x3); + //fs_wb(I2C_MASTER_INT_REG_ADD, 0xf0); + //fs_wb(I2C_MASTER_INT_REG_ADD, 0x00); + + // XXX note that newer designs than the mx21 will also need to check + // and/or set OTG_CORE_INTERRUPT_STEN + + + TRACE_MSG0(otg->ocd->TAG, "--"); + TRACE_MSG0(otg->ocd->TAG, "8. Ready "); + TRACE_MSG1(otg->ocd->TAG, "CINT_STEN: %08x", fs_rl(OTG_CORE_CINT_STEN)); + + local_irq_restore (flags); +} + +extern void mxc_stop_ep(int epn, int dir); + +/*! + * mxc_exit() - de-initialize + */ +void mxc_exit(struct otg_instance *otg) +{ + int i; + unsigned long flags; + TRACE_MSG0(otg->ocd->TAG, "FS_EXIT"); + + //mxc_disable_interrupts(); + //_reg_CRM_PCCR1 &= ~(1<<27); // disable GPT3 + + local_irq_save (flags); + for (i = 0; i < 16; i++) { + mxc_stop_ep(i, USB_DIR_IN); + mxc_stop_ep(i, USB_DIR_OUT); + } + fs_clear_words((volatile u32 *)IO_ADDRESS(OTG_EP_BASE), (32*16/4)); + //fs_clear((void *)IO_ADDRESS(OTG_EP_BASE), 0x200); + //fs_clear((volatile u32 *)IO_ADDRESS(OTG_DMA_BASE), 32*16); + //fs_clear((void *)IO_ADDRESS(OTG_FUNC_BASE), 0x200); + fs_wl( OTG_CORE_HWMODE, 0xa3); + mxc_main_clock_off(); + local_irq_restore (flags); +} + + +/*! + * mxc_ocd_init() - used to initialize/enable or disable the tcd driver + * @param otg + * @param flag + */ +void mxc_ocd_init(struct otg_instance *otg, u8 flag) +{ + TRACE_MSG0(otg->ocd->TAG, "--"); + switch (flag) { + case SET: + TRACE_MSG0(otg->ocd->TAG, "FS_otg->ocd->TAG_EN SET"); + mxc_init(otg); + break; + case RESET: + mxc_exit(otg); + TRACE_MSG0(otg->ocd->TAG, "FS_otg->ocd->TAG_EN RESET"); + break; + } + otg_event(otg, OCD_OK, otg->ocd->TAG, "MX21 OK"); +} + +/* ********************************************************************************************* */ + + +struct ocd_ops ocd_ops; + +extern irqreturn_t mxc_pcd_int_hndlr (void); +extern irqreturn_t mxc_hcd_hw_int_hndlr(int irq, void *dev_id, struct pt_regs *regs); + +extern void mxc_func_clock_on(void); +extern void mxc_func_clock_off(void); +extern void mxc_main_clock_on(void); +extern void mxc_main_clock_off(void); +extern void mxc_set_hw_mode(int); + +#if defined(CONFIG_OTG_USB_PERIPHERAL) || defined(CONFIG_OTG_BDEVICE_WITH_SRP) +irqreturn_t mxc_hcd_hw_int_hndlr(int irq, void *dev_id, struct pt_regs *regs) +{ + return IRQ_HANDLED; +} +#endif /* defined(CONFIG_OTG_USB_PERIPHERAL) || defined(CONFIG_OTG_BDEVICE_WITH_SRP) */ + + +/* ********************************************************************************************* */ +/*! + * ocd_hnp_int_hndlr() - HNP interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t ocd_hnp_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) +{ + u32 hint_stat = fs_rl(OTG_CORE_HINT_STAT); + u32 hnp_cstat = fs_rl(OTG_CORE_HNP_CSTAT); + + /* get and clear interrupts + */ + //fs_wl_set(OCD, OTG_CORE_HINT_STAT, hint_stat); + fs_wl(OTG_CORE_HINT_STAT, hint_stat); + printk(KERN_INFO"%s: HINT_STAT: %08x HNP_CSTAT: %08x\n", __FUNCTION__, hint_stat, hnp_cstat); + + return IRQ_HANDLED; +} + +/*! + * pcd_bwkup_int_hndlr() - wakeup interrupt + * @param irq + * @param dev_id + * @param regs + */ +static irqreturn_t pcd_bwkup_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) +{ + u32 sys_ctrl = fs_rl(OTG_SYS_CTRL); + //static int bwkup_count = 0; + + //TRACE_MSG2(otg->ocd->TAG, "SYS_CTRL: %08x CORE_CLK: %08x", sys_ctrl, fs_rl(OTG_CORE_CLK_CTRL)); + //printk(KERN_INFO"%s: %08x CORE_CLK: %08x\n", __FUNCTION__, sys_ctrl, fs_rl(OTG_CORE_CLK_CTRL)); + + //fs_wl(OTG_SYS_CTRL, sys_ctrl & ~0x0F000000); + mxc_main_clock_on(); // turn on Main Clock + mxc_func_clock_on(); // turn on Function Clock + + //if (bwkup_count++ > 10) + // fs_wl(OTG_SYS_CTRL, 0); + + return IRQ_HANDLED; +} + +/*! + * ocd_dma_int_hndlr() - DMA interrupt + * @param irq + * @param dev_id + * @param regs + */ +static irqreturn_t ocd_dma_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) +{ + u32 dint_stat = fs_rl(OTG_DMA_DINT_STAT); + u32 etd_err = fs_rl(OTG_DMA_ETD_ERR); + u32 ep_err = fs_rl(OTG_DMA_EP_ERR); + + static u32 dma_interrupts = 0; + + dma_interrupts += 1; + + printk(KERN_INFO"%s: dint_stat: %08x etd_err: %08x ep_err: %08x\n", __FUNCTION__, dint_stat, etd_err, ep_err); + + if (dma_interrupts > 10) { + //TRACE_MSG1(otg->ocd->TAG, "DMA INT #%08x disabling DMA error interrupts",dint_stat); + fs_wl(OTG_DMA_DINT_STEN, 0x0); + fs_wl(OTG_DMA_EP_ERR, 0x0); + } + + //TRACE_MSG3(otg->ocd->TAG, "dint_stat: %08x etd_err: %08x ep_err: %08x", dint_stat, etd_err, ep_err); + + if (dint_stat) fs_wl(OTG_DMA_DINT_STAT, dint_stat); + if (etd_err) fs_wl(OTG_DMA_ETD_ERR, etd_err); + if (ep_err) fs_wl(OTG_DMA_EP_ERR, ep_err); + + return IRQ_HANDLED; +} + +/*! + * hcd_host_int_hndlr() - Host interrupt + * @param irq + * @param dev_id + * @param regs + */ +static irqreturn_t hcd_host_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) +{ + u32 sint_stat = fs_rl(OTG_HOST_SINT_STAT); + static u32 hcd_interrupts = 0; + //printk(KERN_INFO"%s: %d\n", __FUNCTION__, hcd_interrupts++); + mxc_hcd_hw_int_hndlr(irq, NULL, regs); + return IRQ_HANDLED; +} + +/*! + * ocd_ctrl_int_hndlr - Control and I2C interrupt + * Process USBOTG related interrupts. + * @param irq + * @param dev_id + * @param regs + */ +static irqreturn_t ocd_ctrl_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) +{ + u32 sys_ctrl = fs_rl(OTG_SYS_CTRL); // C.f. 23.8 USB Control Register + u32 cint_stat = fs_rl(OTG_CORE_CINT_STAT); // C.f. 23.9.2 USBOTG Module Interrupt Status Register + u32 hint_stat = fs_rl(OTG_CORE_HINT_STAT); // C.f. 23.9.12 HNP Interrupt Status Register + u32 hnp_cstat = fs_rl(OTG_CORE_HNP_CSTAT); + + static u32 ocd_interrupts = 0; + + /* N.B. OTG_CORE_CINT_STAT interrupts are self clearing when interrupt + * sources have been cleared. + */ + RETURN_IRQ_HANDLED_UNLESS(cint_stat || hint_stat); + + //if (sys_ctrl & (SYS_CTRL_HOST_WU_INT_STAT | SYS_CTRL_FNT_WU_INT_STAT)) + // TRACE_MSG1(OCD, "SYS_CTRL: HOST/FUNC %08x", sys_ctrl); + + //TRACE_MSG4(OCD, "CLK: %08x sys: %08x cint: %08x hint: %08x", fs_rl(OTG_CORE_CLK_CTRL), sys_ctrl, cint_stat, hint_stat); + + + if (hint_stat) { + //if (hint_stat & HNP_I2COTGINT) + // TRACE_MSG1(OCD, "OTG_CORE_HINT_STAT HNP_I2COTGINT %08x ignored (periodic?)", hint_stat); + + fs_wl(OTG_CORE_HINT_STAT, hint_stat); + printk(KERN_INFO"%s: HINT_STAT: %08x HNP_CSTAT: %08x\n", __FUNCTION__, hint_stat, hnp_cstat); + } + + if (cint_stat & MODULE_ASHNPINT) { // asynchronous HNP interrupt, enable Main clock + u32 hnp_cstat = fs_rl(OTG_CORE_HNP_CSTAT); + u32 hint_stat = fs_rl(OTG_CORE_HINT_STAT); + //TRACE_MSG1(OCD, "MODULE_ASHNPINT %08x", hint_stat); + + mxc_main_clock_on(); // turn on Main Clock + + //if (hnp_cstat & MODULE_ISBDEV) + // TRACE_MSG0(OCD, "ISBDEV"); + + //if (hnp_cstat & MODULE_ISADEV) + // TRACE_MSG0(OCD, "ISADEV"); + + //fs_wl_set(OCD, OTG_CORE_HINT_STAT, hint_stat); + fs_wl(OTG_CORE_HINT_STAT, hint_stat); + ocd_hnp_int_hndlr(irq, dev_id, regs); + } + if (cint_stat & MODULE_ASFCINT) { // Asynchronous Function interrupt, enable Func clock + //TRACE_MSG1(OCD, "MODULE_ASFCINT %08x", cint_stat); + // XXX otg_queue_event(ocd_instance->otg, B_SESS_VLD | A_SESS_VLD, PCD, "MX2ADS ASFCINT"); + mxc_func_clock_on(); // turn on Function Clock + } + + if (cint_stat & MODULE_ASHCINT) { // Asynchronous Host interrupt, enable Host clock + //TRACE_MSG1(OCD, "MODULE_ASHCINT %08x", cint_stat); + mxc_host_clock_on(); // turn on Host Clock + } + + if ((cint_stat & MODULE_HNPINT) || hint_stat) // HNP interrupt + ocd_hnp_int_hndlr(irq, dev_id, regs); + + if (cint_stat & MODULE_FCINT) + mxc_pcd_int_hndlr(); + + if (cint_stat & MODULE_HCINT) { + //TRACE_MSG1(OCD, "MODULE_HCINT %08x", cint_stat); + mxc_hcd_hw_int_hndlr(irq, NULL, regs); + } + + return IRQ_HANDLED; +} + +/* ********************************************************************************************* */ +/*! + * pcd_bwkup_int_hndlr_isr() - main bwkkup interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t pcd_bwkup_int_hndlr_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + //pcd_instance->otg->interrupts++; + //TRACE_MSG0(OCD, "--"); + //printk(KERN_INFO"%s:\n", __FUNCTION__); + return pcd_bwkup_int_hndlr (irq, dev_id, regs); +} + +/*! + * ocd_hnp_int_hndlr_isr() - main ocd hnp interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t ocd_hnp_int_hndlr_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + //pcd_instance->otg->interrupts++; + //TRACE_MSG0(OCD, "--"); + //printk(KERN_INFO"%s:\n", __FUNCTION__); + return ocd_hnp_int_hndlr (irq, dev_id, regs); +} + +/*! + * pcd_func_int_hndlr_isr() - main pcd function interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t pcd_func_int_hndlr_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + //pcd_instance->otg->interrupts++; + //TRACE_MSG0(OCD, "--"); + //printk(KERN_INFO"%s:\n", __FUNCTION__); + //TRACE_MSG1(OCD, "CLK: %08x", fs_rl(OTG_CORE_CLK_CTRL) ); + + return mxc_pcd_int_hndlr(); +} + +/*! + * hcd_host_int_hndlr_isr() - main hcd host interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t hcd_host_int_hndlr_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + //pcd_instance->otg->interrupts++; + //TRACE_MSG0(OCD, "--"); + //printk(KERN_INFO"%s:\n", __FUNCTION__); + return hcd_host_int_hndlr (irq, dev_id, regs); +} + +/*! + * ocd_ctrl_hndlr_isr() - main ocd controller interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t ocd_ctrl_int_hndlr_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + //pcd_instance->otg->interrupts++; + //TRACE_MSG0(OCD, "--"); + //printk(KERN_INFO"%s:\n", __FUNCTION__); + return ocd_ctrl_int_hndlr (irq, dev_id, regs); +} + +/*! + * ocd_dma_int_hndlr_isr() - main dma interrupt handler + * @param irq + * @param dev_id + * @param regs + */ +irqreturn_t ocd_dma_int_hndlr_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + //pcd_instance->otg->interrupts++; + //TRACE_MSG0(OCD, "--"); + return ocd_dma_int_hndlr (irq, dev_id, regs); +} + +/* ********************************************************************************************* */ +extern void mxc_ocd_init (struct otg_instance *otg, u8 flag); +extern int mxc_ocd_mod_init (struct otg_instance *otg); +extern void mxc_ocd_mod_exit (struct otg_instance *otg); + +#if defined(CONFIG_OTG_GPTR) +int mxc_gptcr_start_timer(struct otg_instance *otg, int usec); +#endif /* defined(CONFIG_OTG_GPTR) */ +#if defined(CONFIG_OTG_HRT) +int mxc_hrt_start_timer(struct otg_instance *otg, int usec); +//otg_tick_t mxc_hrt_trace_ticks (void); +//otg_tick_t mxc_hrt_trace_elapsed(otg_tick_t *t1, otg_tick_t *t2); +#endif /* defined(CONFIG_OTG_HRT) */ + +//otg_tick_t l26_ocd_ticks (void); +//otg_tick_t l26_ocd_elapsed(otg_tick_t *t1, otg_tick_t *t2); + +#if defined(CONFIG_OTG_GPTR) +otg_tick_t mxc_gptcr_trace_ticks (void); +otg_tick_t mxc_gptcr_trace_elapsed(otg_tick_t *t1, otg_tick_t *t2); +#endif /* defined(CONFIG_OTG_GPTR) */ +#if defined(CONFIG_OTG_HRT) +otg_tick_t mxc_hrt_trace_ticks (void); +otg_tick_t mxc_hrt_trace_elapsed(otg_tick_t *t1, otg_tick_t *t2); +#endif /* defined(CONFIG_OTG_HRT) */ + +#if !defined(OTG_C99) +struct ocd_ops ocd_ops; +void mxc_ocd_global_init(void) +{ + ZERO(ocd_ops); + #if defined(CONFIG_OTG_TR_AUTO) + ocd_ops.capabilities = OCD_CAPABILITIES_TR | OCD_CAPABILITIES_AUTO; + #else + ocd_ops.capabilities = OCD_CAPABILITIES_TR; + #endif + ocd_ops.ocd_init_func = mxc_ocd_init; + ocd_ops.mod_init = mxc_ocd_mod_init; + ocd_ops.mod_exit = mxc_ocd_mod_exit; +#if defined(CONFIG_OTG_GPTR) + ocd_ops.start_timer = mxc_gptcr_start_timer; + ocd_ops.ticks = mxc_gptcr_trace_ticks; + ocd_ops.elapsed = mxc_gptcr_trace_elapsed; +#endif /* defined(CONFIG_OTG_GPTR) */ +#if defined(CONFIG_OTG_HRT) + ocd_ops.start_timer = mxc_hrt_start_timer; + ocd_ops.ticks = mxc_hrt_trace_ticks; + ocd_ops.elapsed = mxc_hrt_trace_elapsed; +#endif /* defined(CONFIG_OTG_HRT) */ +} +#else /* !defined(OTG_C99) */ +//void mxc_ocd_global_init(void) { + +//} +struct ocd_ops ocd_ops = { + #if defined(CONFIG_OTG_TR_AUTO) + .capabilities = OCD_CAPABILITIES_TR | OCD_CAPABILITIES_AUTO, + #else + .capabilities = OCD_CAPABILITIES_TR, + #endif + .ocd_init_func = mxc_ocd_init, + .mod_init = mxc_ocd_mod_init, + .mod_exit = mxc_ocd_mod_exit, +#if defined(CONFIG_OTG_GPTR) + .start_timer = mxc_gptcr_start_timer, + .ticks = l26_ocd_trace_ticks, + .elapsed = l26_ocd_trace_elapsed, +#endif /* defined(CONFIG_OTG_GPTR) */ +#if defined(CONFIG_OTG_HRT) + .start_timer = mxc_hrt_start_timer, + .ticks = mxc_hrt_trace_ticks, + .elapsed = mxc_hrt_trace_elapsed, +#endif /* defined(CONFIG_OTG_HRT) */ +}; +#endif /* !defined(OTG_C99) */ + +/* ********************************************************************************************* */ + +/*! + * mxc_ocd_mod_init() - initial tcd setup + * Allocate interrupts and setup hardware. + */ +int mxc_ocd_mod_init (struct otg_instance *otg) +{ + int bwkup = request_irq (INT_USB_WAKEUP, pcd_bwkup_int_hndlr_isr, OTG_INTERRUPT, UDC_NAME " USBD BWKUP", NULL); + int func = request_irq (INT_USB_FUNC, pcd_func_int_hndlr_isr, OTG_INTERRUPT, UDC_NAME " USBD FUNC", NULL); + int ctrl = request_irq (INT_USB_CTRL, ocd_ctrl_int_hndlr_isr, OTG_INTERRUPT, UDC_NAME " USBD CTRL", NULL); + //int sof = request_irq (INT_USB_SOF, sof_int_hndlr_isr, OTG_INTERRUPT, UDC_NAME " USBD SOF", NULL); + //int host = request_irq (OTG_USBHOST, hcd_host_int_hndlr_isr, OTG_INTERRUPT, UDC_NAME " USBD HOST", NULL); + int host = 0; + int dma = request_irq (INT_USB_DMA, ocd_dma_int_hndlr_isr, OTG_INTERRUPT, UDC_NAME " USBD DMA", NULL); + + TRACE_MSG0(otg->ocd->TAG, "1. Interrupts requested"); + + RETURN_EINVAL_IF(bwkup || dma || func || host || ctrl); + + return 0; +} + +extern void mxc_stop_ep(int epn, int dir); + +/*! + * mxc_ocd_mod_exit() - de-initialize + */ +void mxc_ocd_mod_exit (struct otg_instance *otg) +{ + #if 1 + int i; + unsigned long flags; + +// fsptrcr_mod_exit(); +// _reg_CRM_PCCR1 &= ~(1<<27); // disable GPT3 + + TRACE_MSG0(otg->ocd->TAG, "free irqs"); +// for (i = INT_USB_WAKEUP; i <= INT_USB_DMA; i++) free_irq (i, NULL); // Free IRQ's + free_irq (INT_USB_WAKEUP, NULL); + free_irq (INT_USB_FUNC, NULL); + free_irq (INT_USB_CTRL, NULL); + free_irq (INT_USB_DMA, NULL); + //free_irq (INT_GPT2, NULL); + //free_irq (INT_GPIO, NULL); + #endif +} + + +/* ********************************************************************************************* */ |