⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_ohci.c

📁 基于s3c2440的U盘读写程序
💻 C
📖 第 1 页 / 共 4 页
字号:
    #else
    wait_ms(1);
    #endif
    if (!maxsize) 
    {
        err("submit_control_message: pipesize for pipe %lx is zero",
        pipe);
        return -1;
    }
    //s_UartPrint("submit_step1 pipe=0x%X\n",pipe);
    if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) 
    {
        gohci.rh.dev = dev;
        /* root hub - redirect */
        //s_UartPrint("submit_step2\n");
        return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
        setup);
    }
    //s_UartPrint("submit_step3\n");
    return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
}


int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, int interval)
{
    info("submit_int_msg");
    return -1;
}


/*-------------------------------------------------------------------------*
 * HC functions
 *-------------------------------------------------------------------------*/
/* reset the HC and BUS */
static int hc_reset (ohci_t *ohci)
{
    int timeout = 30;
    int smm_timeout = 50; /* 0,5 sec */
    if (readl (&ohci->regs->control) & OHCI_CTRL_IR) 
    {
        /* SMM owns the HC */
        writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
        info("USB HC TakeOver from SMM");
        while (readl (&ohci->regs->control) & OHCI_CTRL_IR) 
        {
            wait_ms (10);
            if (--smm_timeout == 0) 
            {
                err("USB HC TakeOver failed!");
                return -1;
            }
        }
    }
    /* Disable HC interrupts */
    writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
    dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;",
    ohci->slot_name,
    readl (&ohci->regs->control));
    /* Reset USB (needed by some controllers) */
    writel (0, &ohci->regs->control);
    /* HC Reset requires max 10 us delay */
    writel (OHCI_HCR,  &ohci->regs->cmdstatus);
    while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) 
    {
        if (--timeout == 0) 
        {
            err("USB HC reset timed out!");
            return -1;
        }
        udelay (1);
    }
    return 0;
}


/*-------------------------------------------------------------------------*/
/* Start an OHCI controller, set the BUS operational
 * enable interrupts
 * connect the virtual root hub */
static int hc_start (ohci_t * ohci)
{
    U32 mask;
    unsigned int fminterval;
    int ints;
    ohci->disabled = 1;
    /* Tell the controller where the control and bulk lists are
    	 * The lists are empty now. */
    writel (0, &ohci->regs->ed_controlhead);
    writel (0, &ohci->regs->ed_bulkhead);
    writel ((U32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
    fminterval = 0x2edf;
    writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
    fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
    writel (fminterval, &ohci->regs->fminterval);
    writel (0x628, &ohci->regs->lsthresh);
    /* start controller operations */
    ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
    ohci->disabled = 0;
    writel (ohci->hc_control, &ohci->regs->control);
    // disable all interrupts //
    mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
    OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
    OHCI_INTR_OC | OHCI_INTR_MIE);
    writel (mask, &ohci->regs->intrdisable);
    // clear all interrupts//	
    mask &= ~OHCI_INTR_MIE;                  //del
    writel (mask, &ohci->regs->intrstatus);//del	
    // Choose the interrupts we care about now  - but w/o MIE //
    mask = (OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO );
    writel (mask, &ohci->regs->intrenable);	
    #ifdef	OHCI_USE_NPS
    /* required for AMD-756 and some Mac platforms */
    writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
    &ohci->regs->roothub.a);
    writel (RH_HS_LPSC, &ohci->regs->roothub.status);
    #endif	/* OHCI_USE_NPS */
/*    
#define mdelay(n) 
    {\
        unsigned long msec=(n); while (msec--) udelay(1000);\
    }
	*/
    
    /* POTPGT delay is bits 24-31, in 2 ms units. */
    mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
    /* connect the virtual root hub */
    ohci->rh.devnum = 0;
    return 0;
}


/*-------------------------------------------------------------------------*/
/* an interrupt happens */
static int hc_interrupt (void)
{
    ohci_t *ohci = &gohci;
    struct ohci_regs *regs = ohci->regs;
    int ints;
    int stat = -1;
    if ((ohci->hcca->done_head != 0) &&
    !(m32_swap (ohci->hcca->done_head) & 0x01)) 
    {
        ints =  OHCI_INTR_WDH;
    } 
    else if ((ints = readl (&regs->intrstatus)) == ~(U32)0) 
    {
        ohci->disabled++;
        err("%s device removed!", ohci->slot_name);
        return -1;
    } 
    else if ((ints &= readl (&regs->intrenable)) == 0) 
    {
    	//ohci_dump (ohci, 1);
        //dbg("hc_interrupt: returning..");
        //=============du add 070302
			#ifdef du_debug
			s_UartPrint("&&&&&&&&&&&&&&&&&&&");
			#endif
			//==========================
        ints = readl (&ohci->regs->intrstatus);
        err("read intrstatus=%x  %x",ints,rHcInterruptStatus);
        ints = readl (&ohci->regs->intrenable);
        err("read intrenable=%x %x",ints,rHcInterruptEnable);
        ints = readl (&ohci->regs->control);
        err("read contorl=%x %x",ints,rHcControl);
        ints = readl (&ohci->regs->cmdstatus);
        err("read cmdstatus=%x %x",ints,rHcCommonStatus);
        return 0xff;
    }
    /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
    if (ints & OHCI_INTR_RHSC) 
    {
        got_rhsc = 1;
        stat = 0xff;
    }
    if (ints & OHCI_INTR_UE) 
    {
        ohci->disabled++;
        err("OHCI Unrecoverable Error, controller usb-%s disabled ",
        ohci->slot_name);
        /* e.g. due to PCI Master/Target Abort */
        #ifdef	DEBUG
        ohci_dump (ohci, 1);
        #else
        wait_ms(1);
        #endif
        /* FIXME: be optimistic, hope that bug won't repeat often. */
        /* Make some non-interrupt context restart the controller. */
        /* Count and limit the retries though; either hardware or */
        /* software errors can go forever... */
        hc_reset (ohci);
        return -1;
    }
    if (ints & OHCI_INTR_WDH) 
    {
        wait_ms(1);
        writel (OHCI_INTR_WDH, &regs->intrdisable);
        stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
        writel (OHCI_INTR_WDH, &regs->intrenable);
    }
    if (ints & OHCI_INTR_SO) 
    {
        err("USB Schedule overrun");
        writel (OHCI_INTR_SO, &regs->intrenable);
        stat = -1;
    }
    /* FIXME:  this assumes SOF (1/ms) interrupts don't get lost... */
    if (ints & OHCI_INTR_SF) 
    {
        unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1;
        wait_ms(1);
        writel (OHCI_INTR_SF, &regs->intrdisable);
        if (ohci->ed_rm_list[frame] != NULL)
        writel (OHCI_INTR_SF, &regs->intrenable);
        stat = 0xff;
    }
    writel (ints, &regs->intrstatus);
    return stat;
}


/*
void hc_interrupt_irq (void)
{
	ohci_t *ohci = &gohci;
	struct ohci_regs *regs = ohci->regs;
	int ints;
	int stat = -1;
       s_UartPrint("i");
	if ((ohci->hcca->done_head != 0) &&
	     !(m32_swap (ohci->hcca->done_head) & 0x01)) {
		ints =  OHCI_INTR_WDH;
	} 
	else if ((ints = readl (&regs->intrstatus)) == ~(U32)0) {
		ohci->disabled++;
		//err ("%s device removed!", ohci->slot_name);
		return -1;
	} else if ((ints &= readl (&regs->intrenable)) == 0) {
               //ohci_dump (ohci, 1);
		//dbg("hc_interrupt: returning..\n");
		//ints = readl (&ohci->regs->intrstatus);
		//s_UartPrint("read intrstatus=%x  %x\n",ints,rHcInterruptStatus);
		//ints = readl (&ohci->regs->intrenable);
		//s_UartPrint("read intrenable=%x %x\n",ints,rHcInterruptEnable);
		//ints = readl (&ohci->regs->control);
		//s_UartPrint("read contorl=%x %x\n",ints,rHcControl);
		//ints = readl (&ohci->regs->cmdstatus);
		//s_UartPrint("read cmdstatus=%x %x\n",ints,rHcCommonStatus);
               s_UartPrint("r");
		return 0xff;
	}
	//dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); 
	if (ints & OHCI_INTR_RHSC) {
		got_rhsc = 1;
		stat = 0xff;
	}
	if (ints & OHCI_INTR_UE) {
		ohci->disabled++;
		err ("OHCI Unrecoverable Error, controller usb-%s disabled",
			ohci->slot_name);
		// e.g. due to PCI Master/Target Abort //
#ifdef	DEBUG
		//ohci_dump (ohci, 1);
#else
		wait_ms(1);
#endif
		//FIXME: be optimistic, hope that bug won't repeat often. ///
		// Make some non-interrupt context restart the controller. ///
		// Count and limit the retries though; either hardware or ///
		// software errors can go forever...///
		hc_reset (ohci);
		return -1;
	}
	if (ints & OHCI_INTR_WDH) {
		wait_ms(1);
		writel (OHCI_INTR_WDH, &regs->intrdisable);
		stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
		writel (OHCI_INTR_WDH, &regs->intrenable);
	}
	if (ints & OHCI_INTR_SO) {
		dbg("USB Schedule overrun\n");
		writel (OHCI_INTR_SO, &regs->intrenable);
		stat = -1;
	}
	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost... //
	if (ints & OHCI_INTR_SF) {
		unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1;
		wait_ms(1);
		writel (OHCI_INTR_SF, &regs->intrdisable);
		if (ohci->ed_rm_list[frame] != NULL)
			writel (OHCI_INTR_SF, &regs->intrenable);
		stat = 0xff;
	}
	writel (ints, &regs->intrstatus);
	//return stat;
	hc_stat=stat;
	return;
}


*/
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/* De-allocate all resources.. */
static void hc_release_ohci (ohci_t *ohci)
{
    info("USB HC release ohci usb-%s", ohci->slot_name);
    if (!ohci->disabled)
    hc_reset (ohci);
}


/*-------------------------------------------------------------------------*/
/*
 * low level initalisation routine, called from usb.c
 */
static char ohci_inited = 0;
int usb_lowlevel_init(void)
{
    unsigned long upllvalue;
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();


 
	/*
    	 * Set the 48 MHz UPLL clocking. Values are taken from
    	 * "PLL value selection guide", 6-23, s3c2410_UM.pdf.
    	 */
	//s_UartPrint("\n &(clk_power->CLKSLOW)=%0x\n",&(clk_power->CLKSLOW));
	//s_UartPrint("\n CLKSLOW=%0x\n",clk_power->CLKSLOW);
    
	clk_power->CLKSLOW |= UCLK_ON ; 
	s_UartPrint("\n &(clk_power->UPLLCON)=%0x\n",&(clk_power->UPLLCON));
	s_UartPrint("\n UPLLCON=%0x\n",clk_power->UPLLCON);
	//s_UartPrint("\n &(clk_power->MPLLCON)=%0x\n",&(clk_power->MPLLCON));
	//s_UartPrint("\n MPLLCON=%0x\n",clk_power->MPLLCON);

    //clk_power->UPLLCON = 0x78023;    //((0x78 << 12) + (2 << 4) + 3);
    //upllvalue = 0x78023;//(0x78<<12)|(0x02<<4)|(0x03); 
    //clk_power->UPLLCON=0x38021;
	upllvalue = 0x38021;
	while (upllvalue != clk_power->UPLLCON) 
    {
        s_UartPrint("\n UPLLCON=%0x\n",clk_power->UPLLCON);
		s_UartPrint("\n upllvalue=%0x\n",upllvalue);
		s_getkey();

		clk_power->UPLLCON = 0x38021;//0x78023;//((0x78 << 12) + (2 << 4) + 3);		
		wait_ms(1);
    }
	
    //gpio->MISCCR |= MISCCR_USBPAD; // 1 = use pads related USB for USB host //
    gpio->MISCCR &= ~MISCCR_USBPAD;//DP0DN0=HOST DP1DN1=DEVICE
    gpio->MISCCR &= ~(MISCCR_USB0_SUSPEND|MISCCR_USB1_SUSPEND); // 1 = use pads related USB for USB host 
	//上面使能USB0 USB1,USB0是 USB host,USB1是USB Device

    clk_power->CLKSLOW &= ~(UCLK_ON | MPLL_OFF | SLOW_BIT); 

    //clk_power->CLKSLOW &= ~UCLK_ON; 
    // Enable USB host clock.
    //clk_power->CLKCON |= CLKCON_USBH;//change by wqh 有问题,下面不能进行
	s_UartPrint("\n clk_power->CLKCON=%0x\n",clk_power->CLKCON);
	memset (&gohci, 0, sizeof (ohci_t));
    memset (&urb_priv, 0, sizeof (urb_priv_t));

    /* align the storage */
	//不懂,为啥跟地址有关

    if ((U32)&ghcca[0] & 0xff) 
    {
        err("HCCA not aligned!!");
        return -1;
    }

	phcca = &ghcca[0];
    //info("aligned ghcca %p", phcca);
    err("\n aligned ghcca %p \n", phcca);//aligned ghcca 301503e4
	memset(&ohci_dev, 0, sizeof(struct ohci_device));

    if ((U32)&ohci_dev.ed[0] & 0x7) 
    {
        err("\n EDs not aligned!! \n");
        return -1;
    }

    memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));

    if ((U32)gtd & 0x7) 
    {
        err("\n TDs not aligned!! \n");
        return -1;
    }

    ptd = gtd;
    gohci.hcca = phcca;
    memset (phcca, 0, sizeof (struct ohci_hcca));
    gohci.disabled = 1;
    gohci.sleeping = 0;
    gohci.irq = -1;
    gohci.regs = (struct ohci_regs *)S3C24X0_USB_HOST_BASE;
    gohci.flags = 0;
    gohci.slot_name = "s3c2410";
    if (hc_reset (&gohci) < 0) 
    {
        hc_release_ohci (&gohci);
        /* Initialization failed */
        clk_power->CLKCON &= ~CLKCON_USBH;
        err("init_step 2\n");
        return -1;
    }
    /* FIXME this is a second HC reset; why?? */
    writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control);
    wait_ms (10);
    if (hc_start (&gohci) < 0) 
    {
        err("can't start usb-%s ", gohci.slot_name);
        hc_release_ohci (&gohci);
        /* Initialization failed */
        clk_power->CLKCON &= ~CLKCON_USBH;
        return -1;
    }
	
    #ifdef	DEBUG
    ohci_dump (&gohci, 1);
    #else
    wait_ms(1);
    #endif
    ohci_inited = 1;
    urb_finished = 1;
    return 0;
}


int usb_lowlevel_stop(void)
{
	
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
    #ifdef du_debug
	s_UartPrint("&&&&&&&&&&&&&&&&&&&");
	#endif
    /* this gets called really early - before the controller has */
    /* even been initialized! */
    if (!ohci_inited)
    return 0;
    /* TODO release any interrupts, etc. */
    /* call hc_release_ohci() here ? */
    hc_reset (&gohci);
    /* may not want to do this */
    clk_power->CLKCON &= ~CLKCON_USBH;//change by wqh 
    return 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -