📄 hc_isp116x.c
字号:
{ hcipriv_t * hp = &hci->hp; __u32 mask; unsigned int fminterval; 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_SO ;// OHCI_INTR_SF; WRITE_REG32 (hci, mask, HcInterruptEnable); WRITE_REG32 (hci, mask, HcInterruptStatus); mask = SOFITLInt | 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 (hci,(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); rh_connect_rh (hci); return 0;}/*-------------------------------------------------------------------------*//* allocate HCI */static hci_t * __devinit hc_alloc_hci (void){ hci_t * hci; hcipriv_t * hp; struct usb_bus * bus; hci = (hci_t *) kmalloc (sizeof (hci_t), GFP_ATOMIC); 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; hci->bh_in_progress = 0; hci->iso_buffer_index = 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); INIT_LIST_HEAD (&hci->itl_list); bus = usb_alloc_bus (&hci_device_operations); if (!bus) { kfree (hci); return NULL; } hci->bus = bus; bus->bus_name = "isp116x"; bus->hcpriv = (void *) hci; hci->bottomHalf.func = hc_interrupt_bh; hci->bottomHalf.data = (unsigned long)hci; hci->ChipReset.func = hc_renew_chip; hci->ChipReset.data = (unsigned long)hci; return hci;}/*-------------------------------------------------------------------------*//* De-allocate all resources.. */static void hc_release_hci (hci_t * hci){ hcipriv_t * hp = &hci->hp; dbg ("USB HC release hci %d", hci->regs); /* disconnect all devices */ if (hci->bus->root_hub) usb_disconnect (&hci->bus->root_hub); if (hp->data_port != -1) { 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); if (hp->data_port != -1) { release_region (hp->data_port, 2); hp->data_port = -1; } if (hp->cmd_port != -1) { release_region (hp->cmd_port, 2); hp->cmd_port = -1; } if (hp->wu_port != -1) { release_region (hp->wu_port, 2); hp->wu_port = -1; } if (hp->irq >= 0) { free_irq (hp->irq, hci); hp->irq = -1; } usb_deregister_bus (hci->bus); usb_free_bus (hci->bus); list_del (&hci->hci_hcd_list); INIT_LIST_HEAD (&hci->hci_hcd_list); kfree (hci);}/*-------------------------------------------------------------------------*//* Increment the module usage count, start the control thread and * return success. */static int __devinit hc_found_hci (int data_port, int cmd_port, int wu_addr, int irq, int dma){ hci_t * hci; hcipriv_t * hp; hci = hc_alloc_hci (); if (!hci) { return -ENOMEM; } hp = &hci->hp; if (!request_region (data_port, 2, "ISP116x USB HOST")) { err ("request address %d-%d failed", data_port, data_port+4); hc_release_hci (hci); return -EBUSY; } hp->data_port = data_port; if (!request_region (cmd_port, 2, "ISP116x USB HOST")) { err ("request address %d-%d failed", data_port, data_port+4); hc_release_hci (hci); return -EBUSY; } hp->cmd_port = cmd_port; if ( wu_addr != -1 ) { if (!request_region (wu_addr, 2, "ISP116x USB HOST")) { err ("request address %d-%d failed", wu_addr, wu_addr+2); hc_release_hci (hci); return -EBUSY; } } hp->wu_port = wu_addr; if ((READ_REG16(hci, HcChipID) & 0xff00) != 0x6100) { printk("ISP116x Not Found. HcChipID = 0x%x\n",READ_REG16(hci, HcChipID)); hc_release_hci (hci); return -ENODEV; } if (hc_reset (hci) < 0) { hc_release_hci (hci); return -ENODEV; } if (hc_alloc_trans_buffer (hci)) { hc_release_hci (hci); return -ENOMEM; } printk(KERN_INFO __FILE__ ": USB ISP116x at %x/%x,%x IRQ %d Rev. %x ChipID: %x\n", data_port, cmd_port, wu_addr, irq, READ_REG32(hci, HcRevision), READ_REG16(hci, HcChipID)); /* FIXME this is a second HC reset; why?? */// WRITE_REG32 (hci, hp->hc_control = OHCI_USB_RESET, HcControl); wait_ms (1000); usb_register_bus (hci->bus); if (request_irq (irq, hc_interrupt, SA_SHIRQ, "ISP116x", hci) != 0) { err ("request interrupt %d failed", irq); hc_release_hci (hci); return -EBUSY; } hp->irq = irq; if (hc_start (hci) < 0) { err ("can't start usb-%x", data_port); hc_release_hci (hci); return -EBUSY; } SITSANG_BIPR_RW = SITSANG_BIPR_USB_HC_IRQ; SITSANG_BIMR_RW |= SITSANG_BIMR_USB_HC_IRQ; return 0;}/*-------------------------------------------------------------------------*/static int __init hci_hcd_init (void){ int ret;#ifdef CONFIG_ARCH_SITSANG unsigned int irq_gpio_pin = 0; irq_gpio_pin = IRQ_TO_GPIO_2_80(SITSANG_USB_HC_IRQ); GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin); set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE); SITSANG_PCR_RW |= SITSANG_PCR_USB_HOST_ON | SITSANG_PCR_PER_ON; SITSANG_BCR_RW |= SITSANG_BCR_BUS_OPEN | SITSANG_BCR_USB_NDP; SITSANG_BCR_RW |= SITSANG_BCR_USB_HC_RESET; mdelay(500); /*Reset the CHIP*/ SITSANG_BCR_RW &= ~(SITSANG_BCR_USB_HC_RESET); mdelay(500); MSC2 &= 0xffff0000; MSC2 |= 0x00009489;#endif ret = hc_found_hci (data_port, cmd_port, wu_port, irq, 0); /* init these data */ for (Buffer_History_p=0; Buffer_History_p<10; Buffer_History_p++) { Buffer_History[Buffer_History_p] = 0; } Buffer_History_p = 0; create_proc_read_entry ("isp_info", 0, NULL, hc_isp_proc_info, NULL); create_proc_read_entry ("isp_reset", 0, NULL, hc_isp_proc_reset, NULL); return ret;}/*-------------------------------------------------------------------------*/static void __exit hci_hcd_cleanup (void){ struct list_head * hci_l; cleanup = 1; 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); } remove_proc_entry("isp_info", NULL);#ifdef CONFIG_ARCH_SITSANG SITSANG_BIMR_RW &= ~SITSANG_BIMR_USB_HC_IRQ; SITSANG_PCR_RW &= ~SITSANG_PCR_USB_HOST_ON;#endif}int hc_isp_proc_info (char *buf, char **start, off_t offset, int count, int *eof, void *data){ int i, j, len = 0; int usec_interval = 0; struct timeval timeVal; do_gettimeofday (&timeVal); j = Buffer_History_p; for (i=0; i<10; i++) { len += sprintf (buf+len,"in hc_interrupt HcBufferStatus: 0x%x \n", Buffer_History[j]); j = (j+1)%10; } len += sprintf (buf+len,"some flags about Buffer: \n"); len += sprintf (buf+len,"\tATL_quirk_flag : %d \n", ATL_quirk_flag); len += sprintf (buf+len,"\tITL0_die_flag : %d \n", ITL0_die_flag); len += sprintf (buf+len,"\tITL1_die_flag : %d \n", ITL1_die_flag); len += sprintf (buf+len,"\n"); len += sprintf (buf+len,"go to force_return count : %d \n", force_return_count); len += sprintf (buf+len,"kernel panic count : %d \n", kernel_panic_count); len += sprintf (buf+len,"itl_list_map error : %d %d %d %d %d \n", itl_list_error[0], itl_list_error[1], \ itl_list_error[2], itl_list_error[3], itl_list_error[4]); if (last_proc_time_sec==-1) { len += sprintf (buf+len,"now we will start to calculate bandwidth!!\n"); last_proc_time_sec = timeVal.tv_sec; last_proc_time_usec = timeVal.tv_usec; proc_itl_stream = 0; } else { usec_interval = (timeVal.tv_sec-last_proc_time_sec)*1000000 + (timeVal.tv_usec-last_proc_time_usec); len += sprintf (buf+len,"USB ITL BandWidth : %dbyte/sec\n", (proc_itl_stream*1000000)/usec_interval); len += sprintf (buf+len,"test interval : %dsec\n", usec_interval/1000000); last_proc_time_sec = timeVal.tv_sec; last_proc_time_usec = timeVal.tv_usec; proc_itl_stream = 0; } return len;}int hc_isp_proc_reset (char *buf, char **start, off_t offset, int count, int *eof, void *data){ int len = 0; len += sprintf (buf+len,"%d", chip_reset); return len;}void hc_renew_chip (unsigned long __hci){ hci_t* hci = (hci_t *)__hci; hcipriv_t * hp = &hci->hp; unsigned int fminterval; int mask; if (hc_reset (hci) < 0) { hc_release_hci (hci); printk (KERN_EMERG "Error in hc_reset, check code!!\n"); return; } WRITE_REG16 (hci, hp->itl_buffer_len, HcITLBufferLength); WRITE_REG16 (hci, hp->atl_buffer_len, HcATLBufferLength); /* Enable IRQ's */ WRITE_REG16 (hci, InterruptPinEnable | HC_HARDWARE_CONFIG, HcHardwareConfiguration); WRITE_REG16 (hci, 0, HcDMAConfiguration); wait_ms (1000); if (hc_start (hci) < 0) { err ("can't start usb-%x", data_port); hc_release_hci (hci); return; } 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_SO ;// OHCI_INTR_SF; WRITE_REG32 (hci, mask, HcInterruptEnable); WRITE_REG32 (hci, mask, HcInterruptStatus); mask = SOFITLInt | ATLInt | OPR_Reg; WRITE_REG16 (hci, mask, HcuPInterrupt); WRITE_REG16 (hci, mask, HcuPInterruptEnable);#ifdef OHCI_USE_NPS WRITE_REG32 (hci,(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); printk (KERN_EMERG "Succeed in renew chip!!\n"); return;} 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 + -