📄 hc_isp116x.c
字号:
InterruptPinEnable | HCR_VALUE, HcHardwareConfiguration); WRITE_REG16 (hci, 0, HcDMAConfiguration); maxlen = (hp->itl_buffer_len > hp->atl_buffer_len) ? hp->itl_buffer_len : hp->atl_buffer_len; hp->tl = kmalloc (maxlen, GFP_KERNEL); if (!hp->tl) return -ENOMEM; memset (hp->tl, 0, maxlen); dbg("hc_alloc_trans_buffer done"); return 0;} static int hc_start (hci_t * hci){ hcipriv_t * hp = &hci->hp; __u32 mask; unsigned int fminterval; dbg("hc_start\n"); fminterval = 0x2edf; fminterval |= ((((fminterval - 210) * 6) / 7) << 16); WRITE_REG32 (hci, fminterval, HcFmInterval); WRITE_REG32 (hci, 0x628, HcLSThreshold); /* start controller operations */ hp->hc_control = OHCI_USB_OPER; WRITE_REG32 (hci, hp->hc_control, HcControl); /* Choose the interrupts we care about now, others later on demand */ mask = OHCI_INTR_MIE | // OHCI_INTR_ATD | // OHCI_INTR_SF | OHCI_INTR_SO;// mask = OHCI_INTR_MIE | OHCI_INTR_SF; WRITE_REG32 (hci, mask, HcInterruptStatus); WRITE_REG32 (hci, mask, HcInterruptEnable); mask = SOFITLInt | ATLInt | OPR_Reg; //commented by xiongly for debug //mask = ATLInt | OPR_Reg;#ifdef HC_SWITCH_INT mask = 0;#endif WRITE_REG16 (hci, mask, HcuPInterrupt); WRITE_REG16 (hci, mask, HcuPInterruptEnable);#ifdef OHCI_USE_NPS WRITE_REG32 ((READ_REG32 (hci, HcRhDescriptorA) | RH_A_NPS) & ~RH_A_PSM, HcRhDescriptorA); WRITE_REG32 (hci, RH_HS_LPSC, HcRhStatus);#endif /* OHCI_USE_NPS */ // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((READ_REG32 (hci, HcRhDescriptorA) >> 23) & 0x1fe); dump_regs(hci); return rh_connect_rh (hci);}/*-------------------------------------------------------------------------*//* allocate HCI */static hci_t * __devinit hc_alloc_hci (void){ hci_t * hci; hcipriv_t * hp; struct usb_bus * bus; DBGFUNC ("enter hc_alloc_hci\n"); hci = (hci_t *) kmalloc (sizeof (hci_t), GFP_KERNEL); if (!hci) return NULL; memset (hci, 0, sizeof (hci_t)); hp = &hci->hp; hp->irq = -1; hp->data_port = -1; hp->cmd_port = -1; hp->wu_port = -1; hci->a_td_array.len = 0; hci->i_td_array[0].len = 0; hci->i_td_array[1].len = 0; hci->td_array = &hci->a_td_array; hci->active_urbs = 0; INIT_LIST_HEAD (&hci->hci_hcd_list); list_add (&hci->hci_hcd_list, &hci_hcd_list); init_waitqueue_head (&hci->waitq); INIT_LIST_HEAD (&hci->ctrl_list); INIT_LIST_HEAD (&hci->bulk_list); INIT_LIST_HEAD (&hci->iso_list); INIT_LIST_HEAD (&hci->intr_list); INIT_LIST_HEAD (&hci->del_list); bus = usb_alloc_bus (&hci_device_operations); if (!bus) { DBGFUNC ("knackered\n"); kfree (hci); return NULL; } hci->bus = bus; bus->bus_name = "isp116x"; bus->hcpriv = (void *) hci; return hci;} /*-------------------------------------------------------------------------*//* De-allocate all resources.. */static void hc_release_hci (hci_t * hci){ hcipriv_t * hp = &hci->hp; DBGFUNC("USB HC release hci %p", hci); if (hp->irq >= 0) { free_irq (hp->irq, hci); hp->irq = -1; } /* disconnect all devices */ if (hci->bus->root_hub) usb_disconnect (&hci->bus->root_hub); if (hp->data_port > 0) { WRITE_REG16 (hci, 0, HcHardwareConfiguration); WRITE_REG16 (hci, 0, HcDMAConfiguration); WRITE_REG16 (hci, 0, HcuPInterruptEnable); }// if (!hci->disabled) hc_reset (hci); if (hp->tl) kfree (hp->tl); /* TODO: We should probably unmap the ports at this point */ if(hci->bus->controller) usb_deregister_bus (hci->bus); /*usb_put_bus (hci->bus); it was moved by usb developers*/ list_del (&hci->hci_hcd_list); INIT_LIST_HEAD (&hci->hci_hcd_list); kfree (hci);}/*-------------------------------------------------------------------------*//*static __inline__ void wait_ms(unsigned int ms){ if(!in_interrupt()) { current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(1 + ms * HZ / 1000); } else mdelay(ms);}*/static void isp116x_set_cpu_int(void){ void * addr; u32 value; /* set irq select and enable */ addr = ioremap(0xFFFFF000,0x40); value = inl(addr+0x00C); value &= ~(((u32)1)<<irq); /*bit3=0*/ outl(value, addr+0x00C); /*select as irq*/ printk(KERN_ALERT" int select reg=0x%.8x\n", (u32)inl(addr+0x00C)); printk(KERN_ALERT" int enable reg=0x%.8x\n", (u32)inl(addr+0x010)); outl(((u32)1)<<irq, addr+0x014); /*disable int 3*/ printk(KERN_ALERT" int enable reg=0x%.8x\n", (u32)inl(addr+0x010)); iounmap(addr); /* set int configuration */ addr = ioremap(0xFFFE2000,0x100); value = inl(addr+0x00); value |= (((u32)1)<<9); outl(value, addr+0x00); /* enable RCPC write */ value = inl(addr+0x80); value &= ~(((u32)0x3)<<(irq*2));#if 1 value |= 0x00 <<(irq*2); /* low level */#else value |= 0x01 <<(irq*2); /* high level */#endif outl(value, addr+0x80); value = inl(addr+0x80); printk(KERN_ALERT" int config reg=0x%.8x\n", value); outl(((u32)1)<<irq, addr+0x84); /* clear int */ value = inl(addr+0x00); value &= ~(((u32)1)<<9); outl(value, addr+0x00); /* disable RCPC write */ iounmap(addr);}/* hc_found_hci * * Check for the existance of the USB HC at the address's specified * and then if its there allocate its private data, iIncrement the * module usage count, start the control thread and return success. */ static int __devinit hc_found_hci (int data_addr, int cmd_addr, int wuaddr, int irq, int dma){ hci_t * hci; hcipriv_t * hp; hci = hc_alloc_hci (); if (!hci) { return -ENOMEM; } hp = &hci->hp;#if 0 /* Request io access to the correct ports */ hp->data_port = (unsigned long) ioremap_nocache(data_addr, 4); hp->cmd_port = (unsigned long) ioremap_nocache(cmd_addr, 4); hp->wu_port = (unsigned long) ioremap_nocache(wuaddr, 4);#else hp->data_port = (unsigned long) data_addr; hp->cmd_port = (unsigned long) cmd_addr; hp->wu_port = (unsigned long) wuaddr;#endif /* * See if we can read the ChipID and prove the chip is there */ if ((READ_REG16(hci, HcChipID) & 0xff00) != 0x6100) { printk("Can't read chip\n"); hc_release_hci (hci); return -ENODEV; } /* * Display the essential details about the chip wot we have * found, including some debug information for now */ printk(KERN_ALERT ": USB ISP116x at %lx/%lx,%lx IRQ %d Rev. %x ChipID: %x\n", hp->data_port, hp->cmd_port, hp->wu_port, irq, READ_REG32(hci, HcRevision), READ_REG16(hci, HcChipID)); printk(KERN_ALERT ": HcControl=0x%x, HcCommandStatus=0x%x\n", READ_REG32(hci, HcControl), READ_REG32(hci, HcCommandStatus) ); printk(KERN_ALERT ": HcInterruptEnable=0x%x HcInterruptDisable=0x%x HcuPinterruptEnable=0x%x\n", READ_REG32(hci, HcInterruptEnable), READ_REG32(hci, HcInterruptDisable), READ_REG16(hci, HcuPInterruptEnable)); printk(KERN_ALERT ": HcHardwareConfiguration=0x%x\n", READ_REG16(hci, HcHardwareConfiguration)); isp116x_set_cpu_int(); dc_set_reg(); /* * Disable All Interrupts */ WRITE_REG16(hci, HCR_VALUE|InterruptPinEnable, HcHardwareConfiguration); WRITE_REG32(hci, 0xffffffff, HcInterruptDisable); WRITE_REG16(hci, 0x0, HcuPInterruptEnable); WRITE_REG16(hci, 0xffff, HcuPInterrupt); /* clear any pending */ WRITE_REG16(hci, HCR_VALUE, HcHardwareConfiguration); if (hc_reset (hci) < 0) { hc_release_hci (hci); return -ENODEV; } if (hc_alloc_trans_buffer (hci)) { hc_release_hci (hci); return -ENOMEM; } dbg("doing final reset"); /* FIXME this is a second HC reset; why?? */ //WRITE_REG32 (hci, hp->hc_control = OHCI_USB_RESET, HcControl); //wait_ms (1000); hci->bus->controller = &isp116x_device->dev; usb_register_bus (hci->bus); if (hc_start (hci) < 0) { err ("can't start usb-%x", data_addr); hc_release_hci (hci); return -EBUSY; } /* * Install the irq handler first - as I was seeing * un-acknowledged interrupts occur during setup */ if (request_irq (irq, isp116x_interrupt, 0, "ISP116x", hci) != 0) { err ("request interrupt %d failed", irq); hc_release_hci (hci); return -EBUSY; } hp->irq = irq; return 0;}/*-------------------------------------------------------------------------*/static int __init hci_hcd_init (void) { int ret; DBGFUNC("hci_hcd_init entered\n"); /* create spinlock for reg accesses */ spin_lock_init(&isp116x_spinlock); isp116x_device = platform_device_register_simple("isp116x", -1, NULL, 0); if (IS_ERR(isp116x_device)) return PTR_ERR(isp116x_device); ret = hc_found_hci (hc_data_port, hc_cmd_port, hc_wu_port, irq, 0); DBGFUNC("hci_hcd_init result=%d\n",ret); if(ret) { platform_device_unregister(isp116x_device); } return ret;}/*-------------------------------------------------------------------------*/static void __exit hci_hcd_cleanup (void) { struct list_head * hci_l; hci_t * hci; for (hci_l = hci_hcd_list.next; hci_l != &hci_hcd_list;) { hci = list_entry (hci_l, hci_t, hci_hcd_list); hci_l = hci_l->next; hc_release_hci(hci); } platform_device_unregister(isp116x_device);}module_init (hci_hcd_init);module_exit (hci_hcd_cleanup);MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>");MODULE_DESCRIPTION ("USB ISP116x Host Controller Driver");MODULE_LICENSE ("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -