📄 usb_ohci.c
字号:
#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 (®s->intrstatus)) == ~(U32)0)
{
ohci->disabled++;
err("%s device removed!", ohci->slot_name);
return -1;
}
else if ((ints &= readl (®s->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, ®s->intrdisable);
stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
writel (OHCI_INTR_WDH, ®s->intrenable);
}
if (ints & OHCI_INTR_SO)
{
err("USB Schedule overrun");
writel (OHCI_INTR_SO, ®s->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, ®s->intrdisable);
if (ohci->ed_rm_list[frame] != NULL)
writel (OHCI_INTR_SF, ®s->intrenable);
stat = 0xff;
}
writel (ints, ®s->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 (®s->intrstatus)) == ~(U32)0) {
ohci->disabled++;
//err ("%s device removed!", ohci->slot_name);
return -1;
} else if ((ints &= readl (®s->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, ®s->intrdisable);
stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
writel (OHCI_INTR_WDH, ®s->intrenable);
}
if (ints & OHCI_INTR_SO) {
dbg("USB Schedule overrun\n");
writel (OHCI_INTR_SO, ®s->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, ®s->intrdisable);
if (ohci->ed_rm_list[frame] != NULL)
writel (OHCI_INTR_SF, ®s->intrenable);
stat = 0xff;
}
writel (ints, ®s->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 + -