/*! * blan_fd_set_configuration - called to indicate set configuration request was received * @param function_instance * @param configuration * @return int */ int blan_fd_set_configuration (struct usbd_function_instance *function_instance, int configuration) { struct usb_network_private *npd = function_instance->privdata; int hs = usbd_high_speed(function_instance); //struct usbd_interface_instance *interface_instance = (struct usbd_interface_instance *)function_instance; TRACE_MSG2(NTT, "CONFIGURED: %d ip_addr: %08x", configuration, npd->ip_addr); //net_check_mesg(mesg_configured); if (npd->eem_os_buffer) net_os_dealloc_buffer(function_instance, npd->eem_os_data, npd->eem_os_buffer); npd->max_recv_urbs = hs ? NETWORK_START_URBS * 3 : NETWORK_START_URBS; otg_atomic_clr(&npd->recv_urbs_started[0]); #ifdef CONFIG_OTG_NETWORK_DOUBLE_OUT otg_atomic_clr(&npd->recv_urbs_started[1]); #endif /* CONFIG_OTG_NETWORK_DOUBLE_OUT */ npd->eem_os_data = npd->eem_os_buffer = NULL; //npd->flags |= NETWORK_CONFIGURED; npd->altsetting = 0; if ((npd->flags & NETWORK_OPEN)) net_os_send_notification_later(function_instance); TRACE_MSG1(NTT, "START RECV npd->flags: %04x", npd->flags); net_fd_start(function_instance); TRACE_MSG1(NTT, "CONFIGURED npd->flags: %04x", npd->flags); return 0; }
int blan_start_recv_endpoint(struct usbd_function_instance *function_instance, int endpoint_index, otg_atomic_t *recv_urbs_started, char *msg) { struct usb_network_private *npd = function_instance->privdata; int i; int hs = usbd_high_speed(function_instance); int alloc_length = usbd_endpoint_transferSize(function_instance, endpoint_index, hs); if (TRACE_VERBOSE) TRACE_MSG4(NTT, "endpoint_index: %d recv_urbs_started: %d alloc_length: %d %s", endpoint_index, otg_atomic_read(recv_urbs_started), alloc_length, msg); while (otg_atomic_read(recv_urbs_started) < npd->max_recv_urbs ) { u8 *os_buffer = NULL; void *os_data = NULL; struct usbd_urb *urb; #ifdef DEBUG_CRC_SEEN if (npd->seen_crc_error) { TRACE_MSG0(NTT, "CRC ERROR NOT RESTARTING"); break; } #endif /* DEBUG_CRC_SEEN */ /* get os buffer - os_buffer is data, os_data is the os data structure */ os_data = net_os_alloc_buffer(function_instance, &os_buffer, alloc_length); /* allocate urb with no buffer */ /*allocate urb without buffer */ urb = usbd_alloc_urb(function_instance, endpoint_index, 0, net_fd_recv_urb2); /* start urb with buffer pointing at the os_buffer in os_data structure */ if (os_buffer && urb) { urb->function_privdata = os_data; urb->buffer = os_buffer; urb->flags |= npd->recv_urb_flags; urb->alloc_length = urb->buffer_length = alloc_length; if (usbd_start_out_urb(urb)) { net_os_dealloc_buffer(function_instance, os_data, os_buffer); urb->function_privdata = NULL; urb->buffer = NULL; usbd_free_urb(urb); } otg_atomic_inc(recv_urbs_started); continue; } TRACE_MSG1(NTT, "recv_urbs_started: %d FAILED EARLY", otg_atomic_read(recv_urbs_started)); if (os_buffer || os_data) net_os_dealloc_buffer(function_instance, os_data, os_buffer); if (urb) urb->buffer = NULL; usbd_free_urb(urb); break; } if (TRACE_VERBOSE) TRACE_MSG1(NTT, "recv_urbs_started: %d", otg_atomic_read(recv_urbs_started)); return 0; }
/*! * mxc_hrt_start_timer() - start a timer for otg state machine * Set or reset timer to interrupt in number of uS (micro-seconds). * * XXX There may be a floor or minimum that can be effectively set. * XXX We have seen an occasional problem with US(25) for discharge for example. * * @param otg * @param usec * @return 0 on success */ int mxc_hrt_start_timer(struct otg_instance *otg, int usec) { ktime_t expires; TRACE_MSG1(otg->ocd->TAG, "usec: %d", usec); g_mxc_hr_active = FALSE; TRACE_MSG1(otg->ocd->TAG, "resetting active: %d", g_mxc_hr_active); hrtimer_cancel(&g_mxc_hrt_timer); if (usec == 0) { goto cancel; } g_mxc_hr_active = TRUE; TRACE_MSG1(otg->ocd->TAG, "setting active: %d", g_mxc_hr_active); if (usec < 100) { TRACE_MSG1(otg->ocd->TAG, "usec: %d set to minimum 100", usec); usec = 100; } hrtimer_init(&g_mxc_hrt_timer, CLOCK_REALTIME, HRTIMER_REL); g_mxc_hrt_timer.function = mxc_hrt_callback; expires = ktime_set(usec / 1000000, (usec % 1000000) * 1000); hrtimer_start(&g_mxc_hrt_timer, expires, HRTIMER_REL); cancel: return 0; }
/*! * mxc_hrt_callback() - called to queue an a timer event to otg queue * @param arg - pointer of hrtimer type */ static int mxc_hrt_callback(struct hrtimer *arg) { TRACE_MSG1(g_otg->ocd->TAG, "checking active: %d", g_mxc_hr_active); if (!g_mxc_hr_active) { return HRTIMER_NORESTART; } g_mxc_hr_active = FALSE; TRACE_MSG1(g_otg->ocd->TAG, "resetting active: %d", g_mxc_hr_active); otg_queue_event(g_otg, TMOUT, g_otg->ocd->TAG, "TMOUT"); return HRTIMER_NORESTART; }
/*! * mxc_hrt_start_timer() - start a timer for otg state machine * Set or reset timer to interrupt in number of uS (micro-seconds). * * XXX There may be a floor or minimum that can be effectively set. * XXX We have seen an occasional problem with US(25) for discharge for example. * * @param otg * @param usec */ int mxc_hrt_start_timer(struct otg_instance *otg, int usec) { TRACE_MSG1(OCD, "usec: %d", usec); mxc_hr_usec_set = usec; //TRACE_MSG1 (OCD, "usec: %d", usec); mxc_hr_active = FALSE; TRACE_MSG1(OCD, "resetting active: %d", mxc_hr_active); del_timer(&hr_timer); RETURN_ZERO_UNLESS(usec); mxc_hr_active = TRUE; TRACE_MSG1(OCD, "setting active: %d", mxc_hr_active); if (mxc_hr_usec_set >= 1000000) { hr_timer.expires = jiffies + ((mxc_hr_usec_set/1000000)*mxc_hr_jiffy_per_sec); hr_timer.arch_cycle_expires = get_arch_cycles(jiffies); TRACE_MSG4 (OCD, "usec: %u jiffies: %8u expires: %8u arch_cycle_expires: %8u LONG", usec, jiffies, hr_timer.expires, hr_timer.arch_cycle_expires); } else { hr_timer.expires = jiffies; hr_timer.arch_cycle_expires = get_arch_cycles(jiffies); if (mxc_hr_usec_set < 100) { TRACE_MSG1(OCD, "usec: %d set to minimum 100", mxc_hr_usec_set); mxc_hr_usec_set = 100; } hr_timer.arch_cycle_expires += nsec_to_arch_cycle(mxc_hr_usec_set * 1000); TRACE_MSG2(OCD, "arch_cycle_expires: %d arch_cycles_per_jiffy: %d", hr_timer.arch_cycle_expires, arch_cycles_per_jiffy); while (hr_timer.arch_cycle_expires >= arch_cycles_per_jiffy) { hr_timer.expires++; hr_timer.arch_cycle_expires -= arch_cycles_per_jiffy; } TRACE_MSG4 (OCD, "usec: %u jiffies: %8u expires: %8u arch_cycle_expires: %8u SHORT", usec, jiffies, hr_timer.expires, hr_timer.arch_cycle_expires); } add_timer(&hr_timer); return 0; }
void pmic_se1i_handler(void) { TRACE_MSG0(REMOVE_TCD, "--"); pmic_otg_wakeup(); #if 0 #if 1 t_sensor_bits sense_bits; if (pmic_get_sensors(&sense_bits)) { printk(KERN_INFO "%s: pmic_get_sensors() failed\n", __FUNCTION__); return; } TRACE_MSG1(REMOVE_TCD, "MC13783 EVENT: se1: %d", sense_bits.sense_se1s); otg_event(tcd_instance->otg, (sense_bits.sense_se1s ? SE1_DET : SE1_DET_), REMOVE_TCD, "MC13783 SE1"); #else otg_event(tcd_instance->otg, (pmic_check_sense(sense_se1s) ? SE1_DET : SE1_DET_), REMOVE_TCD, "MC13783 SE1"); #endif #endif }
/*! * mxc_gptcr_timer_int_hndlr() - timer interrupt * @param irq * @param dev_id * @param regs */ irqreturn_t mxc_gptcr_timer_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) { u32 gptsr = *_reg_GPT_GPTSR; *_reg_GPT_GPTIR &= ~(0x04); if (gptsr & (0x01 << 2)){ TRACE_MSG7(OCD, "cnt: %08x match: %08x gptsr: %08x GPTCNT: %08x GPTCR: %08x GPTSR: %08x GPTOCR3: %08x\n", mxc_gptcr_ticks_set, mxc_gptcr_match_set, gptsr, *_reg_GPT_GPTCNT, *_reg_GPT_GPTCR, *_reg_GPT_GPTSR, *_reg_GPT_GPTOCR3); *_reg_GPT_GPTCR &= ~(0x7 << 26); *_reg_GPT_GPTOCR3 = 0; TRACE_MSG0(OCD, "OCM3"); TRACE_MSG1(OCD, "active: %x", mxc_gptcr_active); if (mxc_gptcr_active) { TRACE_MSG0(OCD, "calling otg_event"); mxc_gptcr_active = 0; otg_event(ocd_instance->otg, TMOUT, OCD, "TMOUT"); } else { TRACE_MSG0(OCD, "skipping otg_event"); } *_reg_GPT_GPTSR |= 0x4; return IRQ_HANDLED; } if (!mxc_shared_int) *_reg_GPT_GPTIR |= 0x4; return IRQ_NONE; }
/*! net_fd_start_xmit_nocrc * @brief - start sending a buffer * * @param function_instance - pointer to this function instance * @param buffer buffer containing data to send * @param len - length of data to send * @param data instance data * @return: 0 if all OK * -EINVAL, -EUNATCH, -ENOMEM * rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above) * Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped. */ int net_fd_start_xmit_nocrc (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb = NULL; int rc; int in_pkt_sz; u8 *cp; u32 crc; #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN int xmit_index = 0; int endpoint_index = BULK_IN_A; #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1])) ? 0 : 1; int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A; #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */ TRACE_MSG7(NTT,"npd: %p function: %p flags: %04x len: %d endpoint_index: %d xmit_started: %d %d", npd, function_instance, npd->flags, len, endpoint_index, otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1])); in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, endpoint_index, usbd_high_speed(function_instance)); /* allocate urb 5 bytes larger than required */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa); return -ENOMEM; } urb->actual_length = len; memcpy (urb->buffer, buffer, len); urb->function_privdata = data; urb->actual_length = len; otg_atomic_add(urb->actual_length, &npd->queued_bytes); otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]); if ((rc = usbd_start_in_urb (urb))) { TRACE_MSG1(NTT,"FAILED: %d", rc); printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc); urb->function_privdata = NULL; otg_atomic_sub(urb->actual_length, &npd->queued_bytes); otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]); usbd_free_urb (urb); return rc; } return 0; }
void mxc_hrt_callback (unsigned long arg) { TRACE_MSG1(OCD, "checking active: %d", mxc_hr_active); RETURN_UNLESS(mxc_hr_active); mxc_hr_active = FALSE; TRACE_MSG1(OCD, "resetting active: %d", mxc_hr_active); if (mxc_hr_usec_set >= 1000000) { //if requested period is in the range of 1 sec hr_timer.expires = jiffies + ((mxc_hr_usec_set/1000000)*mxc_hr_jiffy_per_sec); hr_timer.arch_cycle_expires = get_arch_cycles(jiffies); hr_timer.function = mxc_hrt_callback; } else { hr_timer.expires = jiffies; hr_timer.arch_cycle_expires = get_arch_cycles(jiffies); if (mxc_hr_usec_set < 100) { TRACE_MSG1(OCD, "usec: %d set to minimum 100", mxc_hr_usec_set); mxc_hr_usec_set = 100; } hr_timer.arch_cycle_expires += nsec_to_arch_cycle(mxc_hr_usec_set * 1000); //hr_timer.arch_cycle_expires += nsec_to_arch_cycle(100 * 1000 * 1000); while (hr_timer.arch_cycle_expires >= arch_cycles_per_jiffy) { hr_timer.expires++; hr_timer.arch_cycle_expires -= arch_cycles_per_jiffy; } } //end of else TRACE_MSG3 (OCD, "usec: %d expires: %8u arch_cycle_expires: %8u", mxc_hr_usec_set, hr_timer.expires, hr_timer.arch_cycle_expires); otg_event(ocd_instance->otg, TMOUT, OCD, "TMOUT"); // add_timer(&hr_timer); }
static irqreturn_t gpio_c16_int_hndlr(int irq, void *dev_id, struct pt_regs *regs) { udelay(100); if (gpio_get_data(2, 16) == 1) { det_dp_hi = 1; // mc13783_otg_wakeup (); // gpio_config_int_en(2, 17, FALSE); } else { det_dp_hi = 0; // gpio_config_int_en(2, 16, TRUE); } TRACE_MSG1(REMOVE_TCD, "Changing the state of DP to %d", det_dp_hi); pmic_otg_wakeup(); return IRQ_HANDLED; }
/*! safe_mod_init * @param function The function instance */ int safe_mod_init (void) { struct usbd_class_ethernet_networking_descriptor *ethernet; struct usbd_class_network_channel_descriptor *channel; int len = 0; char buf[255]; buf[0] = 0; #if 0 // Update the iMACAddress field in the ethernet descriptor { char address_str[14]; snprintf(address_str, 13, "%02x%02x%02x%02x%02x%02x", remote_dev_addr[0], remote_dev_addr[1], remote_dev_addr[2], remote_dev_addr[3], remote_dev_addr[4], remote_dev_addr[5]); if ((ethernet = &safe_class_4)) { if (ethernet->iMACAddress) { usbd_free_string_descriptor(ethernet->iMACAddress); } ethernet->iMACAddress = usbd_alloc_string(function_instance, address_str); } } #endif #ifdef CONFIG_OTG_NETWORK_SAFE_PADBEFORE safe_class_3.bmDataCapabilities |= BMDATA_PADBEFORE; len += sprintf(buf + len, "PADBEFORE: %02x ", safe_class_3.bmDataCapabilities); #endif #ifdef CONFIG_OTG_NETWORK_SAFE_CRC safe_class_3.bmDataCapabilities |= BMDATA_CRC; len += sprintf(buf + len, "CRC: %02x ", safe_class_3.bmDataCapabilities); #endif #ifndef CONFIG_OTG_NETWORK_SAFE_BRIDGED safe_class_3.bmNetworkCapabilities |= BMNETWORK_NONBRIDGED; len += sprintf(buf + len, "NONBRIDGE: %02x ", safe_class_3.bmNetworkCapabilities); #endif if (strlen(buf)) TRACE_MSG1(NTT,"%s", buf); return usbd_register_interface_function (&safe_interface_driver, "net-safe-if", NULL); }
/*! arc_read_rcv_buffer * * Recover number of bytes DMA'd to receive buffer, sync. */ int arc_read_rcv_buffer (struct pcd_instance *pcd, struct usbd_endpoint_instance *endpoint) { struct arc_private_struct *privdata = endpoint->privdata; struct ep_td_struct *curr_td = privdata->cur_dtd; struct ep_queue_head *qh = privdata->cur_dqh; struct usbd_urb *rx_urb = endpoint->rcv_urb; /* sync qh and td structures, note that urb-buffer was invalidated in arc_add_buffer_to_dtd() */ dma_cache_maint(qh, sizeof(struct ep_queue_head), DMA_FROM_DEVICE); dma_cache_maint(curr_td, sizeof(struct ep_td_struct), DMA_FROM_DEVICE); if (rx_urb) { int length = rx_urb->buffer_length - ((le32_to_cpu(curr_td->size_ioc_sts) & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS); if (TRACE_VERBOSE) TRACE_MSG4(pcd->TAG, "buffer_length: %d alloc_length: %d Len: %d (%x)" , rx_urb->buffer_length, rx_urb->alloc_length, length, le32_to_cpu(curr_td->size_ioc_sts)); return length; } TRACE_MSG1(pcd->TAG, "NO RCV URB (%x)" , le32_to_cpu(curr_td->size_ioc_sts)); return 0; }
/*! * generic_cf_register() * */ void generic_cf_register(struct generic_config *config, char *match) { char *cp, *sp, *lp; int i; char **interface_list = NULL; int interfaces = 0; //printk(KERN_INFO"%s: Driver: \"%s\" idVendor: %04x idProduct: %04x interface_names: \"%s\" match: \"%s\"\n", // __FUNCTION__, // config->composite_driver.driver.name, MODPARM(idVendor), MODPARM(idProduct), config->interface_names, // match ? match : ""); TRACE_MSG5(GENERIC, "Driver: \"%s\" idVendor: %04x idProduct: %04x interface_names: \"%s\" match: \"%s\"", config->composite_driver.driver.name, MODPARM(idVendor), MODPARM(idProduct), config->interface_names, match ? match : ""); RETURN_IF (match && strlen(match) && strcmp(match, config->composite_driver.driver.name)); //printk(KERN_INFO"%s: MATCHED\n", __FUNCTION__); /* decompose interface names to construct interface_list */ RETURN_UNLESS (config->interface_names && strlen(config->interface_names)); /* count interface names and allocate _interface_names array */ for (cp = sp = config->interface_names, interfaces = 0; cp && *cp; ) { for (; *cp && *cp == ':'; cp++); // skip white space sp = cp; // save start of token for (; *cp && *cp != ':'; cp++); // find end of token BREAK_IF (sp == cp); if (*cp) cp++; interfaces++; } THROW_UNLESS(interfaces, error); TRACE_MSG1(GENERIC, "interfaces: %d", interfaces); THROW_UNLESS((interface_list = (char **) CKMALLOC (sizeof (char *) * (interfaces + 1), GFP_KERNEL)), error); for (cp = sp = config->interface_names, interfaces = 0; cp && *cp; interfaces++) { for (; *cp && *cp == ':'; cp++); // skip white space sp = cp; // save start of token for (; *cp && *cp != ':'; cp++); // find end of token BREAK_IF (sp == cp); lp = cp; if (*cp) cp++; *lp = '\0'; lp = CKMALLOC(strlen(sp), GFP_KERNEL); strcpy(lp, sp); interface_list[interfaces] = lp; TRACE_MSG3(GENERIC, "INTERFACE[%2d] %x \"%s\"", interfaces, interface_list[interfaces], interface_list[interfaces]); } config->composite_driver.device_description = &config->device_description; config->composite_driver.configuration_description = &config->configuration_description; config->composite_driver.driver.fops = &generic_function_ops; config->interface_list = interface_list; THROW_IF (usbd_register_composite_function ( &config->composite_driver, config->composite_driver.driver.name, config->class_name, config->interface_list, NULL), error); config->registered++; TRACE_MSG0(GENERIC, "REGISTER FINISHED"); CATCH(error) { otg_trace_invalidate_tag(GENERIC); } }
/*! * otg_pci_probe() - otg pci probe function * * Get the standard PCI resources allocated. * */ int __devinit otg_pci_probe (struct pci_dev *pci_dev, const struct pci_device_id *id, struct otg_pci_driver *otg_pci_driver) { struct otg_driver *otg_driver; struct otg_dev *otg_dev = NULL; int enabled = 0; int irq = 0; int region; u8 latency, limit; /* allocate otg_dev structure and fill in standard fields */ THROW_UNLESS((otg_dev = kmalloc(sizeof(struct otg_dev), SLAB_KERNEL)), error); memset(otg_dev, 0, sizeof(struct otg_dev)); otg_dev->PCI = otg_trace_obtain_tag(); //printk(KERN_INFO"%s: PCI %d\n", __FUNCTION__, otg_dev->PCI); //TRACE_MSG0(otg_dev->PCI, "TEST"); THROW_UNLESS((enabled = !pci_enable_device(pci_dev)), error); otg_dev->otg_pci_driver = otg_pci_driver; otg_dev->pci_regions = otg_pci_driver->pci_regions; pci_set_drvdata(pci_dev, otg_dev); printk(KERN_INFO"%s: pci_dev: %x otg_dev: %x drv_data: %x\n", __FUNCTION__, pci_dev, otg_dev, pci_get_drvdata(pci_dev)); for (region = 0; region < DEVICE_COUNT_RESOURCE; region++) { unsigned long resource_start; unsigned long resource_len; TRACE_MSG5(otg_dev->PCI, "[%2d] flags: %08x start: %08x end: %08x len: %08x", region, pci_resource_flags(pci_dev, region), pci_resource_start(pci_dev, region), pci_resource_end(pci_dev, region), pci_resource_len(pci_dev, region) ); CONTINUE_UNLESS(otg_dev->pci_regions & (1 << region)); resource_start = pci_resource_start(pci_dev, region); resource_len = pci_resource_len(pci_dev, region); TRACE_MSG5(otg_dev->PCI, "pci_dev: %x otg_dev: %x start: %lx len: %lx name: %s", pci_dev, otg_dev, resource_start, resource_len, otg_pci_driver->name); THROW_UNLESS(request_mem_region(resource_start, resource_len, otg_pci_driver->name), error); THROW_UNLESS((otg_dev->regs[region] = ioremap_nocache(resource_start, resource_len)), error); TRACE_MSG2(otg_dev->PCI, "regs[%d] %x", region, otg_dev->regs[region]); } THROW_UNLESS((irq = !request_irq(pci_dev->irq, otg_pci_isr, SA_SHIRQ, otg_pci_driver->name, pci_dev)), error); TRACE_MSG1(otg_dev->PCI, "irq: %d", pci_dev->irq); /* bad pci latencies can contribute to overruns - but where ?? */ pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &latency); pci_read_config_byte (pci_dev, PCI_MAX_LAT, &limit); TRACE_MSG2(otg_dev->PCI, "latency: %02x limit: %02x", latency, limit); if (latency && /* limit &&*/ (limit < latency)) { pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, limit); pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &latency); TRACE_MSG2(otg_dev->PCI, "latency: %02x limit: %02x", latency, limit); } /* XXX lock? */ otg_dev->id = otg_get_id(pci_dev); TRACE_MSG1(otg_dev->PCI, "id: %d", otg_dev->id); if (otg_devs) { TRACE_MSG2(otg_dev->PCI, "otg_devs: %x new: %x", otg_devs, otg_dev); otg_dev->next = otg_devs; } otg_devs = otg_dev; return 0; CATCH(error) { printk(KERN_INFO"%s: FAILED\n", __FUNCTION__); pci_set_drvdata(pci_dev, NULL); if (irq) free_irq(pci_dev->irq, otg_dev); otg_pci_free_dev(pci_dev, otg_dev); if (otg_dev) kfree(otg_dev); if (enabled) pci_disable_device(pci_dev); return -EINVAL; } }
/*! * @brief blan_fd_reset - called to indicate bus has been reset * @param function_instance * @return int */ int blan_fd_reset (struct usbd_function_instance *function_instance) { struct usb_network_private *npd = function_instance->privdata; TRACE_MSG1(NTT,"RESET %08x",npd->ip_addr); return net_fd_stop (function_instance); }
/*! blan_fd_device_request * @brief process a received SETUP URB * * Processes a received setup packet and CONTROL WRITE data. * Results for a CONTROL READ are placed in urb->buffer. * * @param function_instance - pointer to this function instance * @param request - received request to interface or endpoint * @return non-zero for failure. */ int blan_fd_device_request (struct usbd_function_instance *function_instance, struct usbd_device_request *request) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb; int index; /* Verify that this is a USB Class request per CDC specification or a vendor request. */ RETURN_ZERO_IF (!(request->bmRequestType & (USB_REQ_TYPE_CLASS | USB_REQ_TYPE_VENDOR))); /* Determine the request direction and process accordingly */ switch (request->bmRequestType & (USB_REQ_DIRECTION_MASK | USB_REQ_TYPE_MASK)) { case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_VENDOR: switch (request->bRequest) { case MCCI_ENABLE_CRC: //if (make_crc_table()) // return -EINVAL; //npd->encapsulation = simple_crc; return 0; case BELCARRA_PING: TRACE_MSG1(NTT,"H2D VENDOR IP: %08x", npd->ip_addr); if ((npd->network_type == network_blan)) net_os_send_notification_later(function_instance); break; #if !defined(CONFIG_OTG_NETWORK_BLAN_DO_NOT_SETTIME) || !defined(CONFIG_OTG_NETWORK_SAFE_DO_NOT_SETTIME) case BELCARRA_SETTIME: npd->rfc868time = ntohl( request->wValue << 16 | request->wIndex); net_os_settime(function_instance, npd->rfc868time); break; #endif case BELCARRA_SETIP: #ifdef OTG_BIG_ENDIAN npd->ip_addr = ntohl( request->wValue | request->wIndex<< 16 ); #else /* OTG_BIG_ENDIAN */ npd->ip_addr = ntohl( request->wValue << 16 | request->wIndex); #endif /* OTG_BIG_ENDIAN */ TRACE_MSG1(NTT, "npd->ip_addr: %08x", npd->ip_addr); // XXX need to get in correct order here // XXX what about locally set mac addr // XXX UNLESS(npd->local_dev_set) { if (!(npd->override_MAC)) { npd->local_dev_addr[0] = 0xfe | 0x02; /* locally administered */ npd->local_dev_addr[1] = 0x00; npd->local_dev_addr[2] = (npd->ip_addr >> 24) & 0xff; npd->local_dev_addr[3] = (npd->ip_addr >> 16) & 0xff; npd->local_dev_addr[4] = (npd->ip_addr >> 8) & 0xff; npd->local_dev_addr[5] = (npd->ip_addr >> 0) & 0xff; } // XXX } break; case BELCARRA_SETMSK: #ifdef OTG_BIG_ENDIAN npd->network_mask = ntohl( request->wValue | request->wIndex << 16); #else /* OTG_BIG_ENDIAN */ npd->network_mask = ntohl( request->wValue << 16 | request->wIndex); #endif /* OTG_BIG_ENDIAN */ TRACE_MSG1(NTT, "npd->network_mask: %08x", npd->network_mask); break; case BELCARRA_SETROUTER: #ifdef OTG_BIG_ENDIAN npd->router_ip = ntohl( request->wValue | request->wIndex << 16); #else /* OTG_BIG_ENDIAN */ npd->router_ip = ntohl( request->wValue << 16 | request->wIndex); #endif /* OTG_BIG_ENDIAN */ TRACE_MSG1(NTT, "npd->router_ip: %08x", npd->router_ip); break; case BELCARRA_SETDNS: #ifdef OTG_BIG_ENDIAN npd->dns_server_ip = ntohl( request->wValue | request->wIndex < 16); #else /* OTG_BIG_ENDIAN */ npd->dns_server_ip = ntohl( request->wValue << 16 | request->wIndex); #endif /* OTG_BIG_ENDIAN */ break; #ifdef CONFIG_OTG_NETWORK_BLAN_FERMAT case BELCARRA_SETFERMAT: npd->fermat = 1; break; #endif #ifdef CONFIG_OTG_NETWORK_BLAN_HOSTNAME case BELCARRA_HOSTNAME: TRACE_MSG0(NTT,"HOSTNAME"); RETURN_EINVAL_IF(!(urb = usbd_alloc_urb_ep0(function_instance, le16_to_cpu(request->wLength), blant_fd_urb_received_ep0) )); RETURN_ZERO_IF(!usbd_start_out_urb(urb)); // return if no error usbd_free_urb(urb); // de-alloc if error return -EINVAL; #endif #ifdef CONFIG_OTG_NETWORK_BLAN_DATA_NOTIFY_OK case BELCARRA_DATA_NOTIFY: TRACE_MSG0(NTT,"DATA NOTIFY"); npd->data_notify = 1; return -EINVAL; #endif } switch (request->bRequest) { case BELCARRA_SETIP: case BELCARRA_SETMSK: case BELCARRA_SETROUTER: TRACE_MSG5(NTT, "npd->network_mask: %08x npd->ip_addr: %08x npd->router_ip: %08x flags: %08x %s", npd->network_mask, npd->ip_addr, npd->router_ip, npd->flags, (npd->flags & NETWORK_CONFIGURED) ? "CONFIGURED" : ""); BREAK_UNLESS (npd->network_mask && npd->ip_addr && npd->router_ip && (npd->flags & NETWORK_CONFIGURED)); // let the os layer know, if it's interested. #ifdef CONFIG_OTG_NETWORK_BLAN_AUTO_CONFIG net_os_config(function_instance); net_os_hotplug(function_instance); #endif /* CONFIG_OTG_NETWORK_BLAN_AUTO_CONFIG */ break; } return 0; default: break; }
/*! arc_pcd_start */ void arc_pcd_start (struct pcd_instance *pcd) { u32 id = (u32) UOG_ID; TRACE_MSG1(pcd->TAG, "Initialize UDC and start id: %08x", id); arc_udc_run (); }
/*! * zasevb_modinit() - linux module initialization * * This needs to initialize the hcd, pcd and tcd drivers. This includes tcd and possibly hcd * for some architectures. * */ static int zasevb_modinit (void) { struct otg_instance *otg = NULL; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) struct clk *clk = clk_get(NULL, "usb_clk"); clk_enable(clk); clk_put(clk); #endif THROW_UNLESS((otg = otg_create()), error); mxc_pcd_ops_init(); #if !defined(OTG_C99) pcd_global_init(); fs_ocd_global_init(); zasevb_tcd_global_init(); fs_pcd_global_init(); #endif /* !defined(OTG_C99) */ ZAS = otg_trace_obtain_tag(otg, "zas"); mxc_procfs_init(); TRACE_MSG0(ZAS, "1. ZAS"); #if 0 /* ZAS EVB Platform setup */ TRACE_MSG4(ZAS, "BCTRL Version: %04x Status: %04x 1: %04x 2: %04x", readw(PBC_BASE_ADDRESS ), readw(PBC_BASE_ADDRESS + PBC_BSTAT), readw(PBC_BASE_ADDRESS + PBC_BCTRL1_SET), readw(PBC_BASE_ADDRESS + PBC_BCTRL2_SET)); #endif /* ZAS EVB Clock setup */ #if defined(CONFIG_ARCH_ARGONPLUS) || defined(CONFIG_ARCH_ARGONLV) #define ZASEVB_MULTIPLIER 12 #define ZASEVB_DIVISOR 775 // ~10. #else #define ZASEVB_MULTIPLIER 12 #define ZASEVB_DIVISOR 155 #endif TRACE_MSG0(ZAS, "2. Setup GPT"); THROW_UNLESS(ocd_instance = otg_set_ocd_ops(otg, &ocd_ops), error); REMOVE_OCD = ocd_instance->TAG; // XXX THROW_IF((ocd_ops.mod_init ? ocd_ops.mod_init() : 0), error); #if defined(CONFIG_OTG_GPTR) mxc_gptcr_mod_init(ZASEVB_DIVISOR, ZASEVB_MULTIPLIER); #endif /* defined(CONFIG_OTG_GPTR) */ #if defined(CONFIG_OTG_HRT) mxc_hrt_mod_init(otg, ZASEVB_DIVISOR, ZASEVB_MULTIPLIER); #endif /* defined(CONFIG_OTG_GPTR) */ #if !defined(CONFIG_USB_HOST) TRACE_MSG0(ZAS, "3. PCD"); THROW_UNLESS(REMOVE_pcd_instance = otg_set_pcd_ops(otg, &pcd_ops), error); REMOVE_PCD = REMOVE_pcd_instance->TAG; // XXX THROW_IF((pcd_ops.mod_init ? pcd_ops.mod_init() : 0), error); #else /* !defined(CONFIG_USB_HOST) */ printk(KERN_INFO"%s: PCD DRIVER N/A\n", __FUNCTION__); #endif /* !defined(CONFIG_USB_HOST) */ TRACE_MSG0(ZAS, "4. TCD"); THROW_UNLESS(REMOVE_tcd_instance = otg_set_tcd_ops(otg, &tcd_ops), error); REMOVE_TCD = REMOVE_tcd_instance->TAG; // XXX THROW_IF((tcd_ops.mod_init ? tcd_ops.mod_init() : 0), error); #ifdef OTG_USE_I2C TRACE_MSG0(ZAS, "0. I2C"); i2c_mod_init(otg); #endif #if defined(CONFIG_OTG_USB_HOST) || defined(CONFIG_OTG_USB_PERIPHERAL_OR_HOST)|| defined(CONFIG_OTG_DEVICE) TRACE_MSG0(ZAS, "5. Host"); THROW_UNLESS(hcd_instance = otg_set_hcd_ops(otg, &hcd_ops), error); HCD = hcd_instance->TAG; // XXX THROW_IF((hcd_ops.mod_init) ? hcd_ops.mod_init() : 0, error); #else /* defined(CONFIG_OTG_USB_HOST) || defined(CONFIG_OTG_USB_PERIPHERAL_OR_HOST)|| defined(CONFIG_OTG_DEVICE) */ printk(KERN_INFO"%s: HCD DRIVER N/A\n", __FUNCTION__); #endif /* defined(CONFIG_OTG_USB_HOST) || defined(CONFIG_OTG_USB_PERIPHERAL_OR_HOST)|| defined(CONFIG_OTG_DEVICE) */ TRACE_MSG0(ZAS, "6. Init & check"); THROW_IF((ocd_ops.mod_init ? ocd_ops.mod_init(otg) : 0), error); #if !defined(CONFIG_USB_HOST) THROW_IF((pcd_ops.mod_init ? pcd_ops.mod_init(otg) : 0), error); #endif /* !defined(CONFIG_USB_HOST) */ THROW_IF((tcd_ops.mod_init ? tcd_ops.mod_init(otg) : 0), error); #if defined(CONFIG_OTG_USB_HOST) || defined(CONFIG_OTG_USB_PERIPHERAL_OR_HOST)|| defined(CONFIG_OTG_DEVICE) THROW_IF((hcd_ops.mod_init) ? hcd_ops.mod_init(otg) : 0, error); #endif /* defined(CONFIG_OTG_USB_HOST) || defined(CONFIG_OTG_USB_PERIPHERAL_OR_HOST)|| defined(CONFIG_OTG_DEVICE) */ THROW_UNLESS(ocd_instance && (otg = ocd_instance->otg), error); TRACE_MSG0(ZAS, "7. otg_init"); if (MODPARM(serial_number_str) && strlen(MODPARM(serial_number_str))) { TRACE_MSG1(ZAS, "serial_number_str: %s", MODPARM(serial_number_str)); otg_serial_number (otg, MODPARM(serial_number_str)); } otg_init(otg); return 0; CATCH(error) { //zasevb_modexit(); return -EINVAL; } return 0; }
/*! net_fd_recv_urb_mdlm * @brief callback to process a received URB * * @param urb - pointer to received urb * @param rc - dummy parameter * @return non-zero for failure. */ int net_fd_recv_urb_mdlm(struct usbd_urb *urb, int rc) { struct usbd_function_instance *function_instance = urb->function_instance; struct usb_network_private *npd = function_instance->privdata; void *os_data = NULL; void *os_buffer = NULL; int crc_bad = 0; int trim = 0; int len; u32 crc; u32 temmp; len = urb->actual_length; trim = 0; //TRACE_MSG2(NTT, "status: %d actual_length: %d", urb->status, urb->actual_length); //RETURN_EINVAL_IF (urb->status == USBD_URB_OK); os_data = urb->function_privdata; //TRACE_MSG2(NTT, "os_data: %x os_buffer: %x", os_data, os_buffer); #if defined(CONFIG_OTG_NETWORK_BLAN_PADAFTER) { /* This version simply checks for a correct CRC along the * entire packet. Some UDC's have trouble with some packet * sizes, this allows us to add pad bytes after the CRC. */ u8 *src = urb->buffer; int copied; // XXX this should work, but the MIPS optimizer seems to get it wrong.... //copied = (len < urb->wMaxPacketSize) ? 0 : ((len / urb->wMaxPacketSize) - 1) * urb->wMaxPacketSize; if (len < urb->wMaxPacketSize*2) copied = 0; else { int pkts = ((len - urb->wMaxPacketSize) / urb->wMaxPacketSize); copied = (pkts - 1) * urb->wMaxPacketSize; } len -= copied; crc = CRC32_INIT; for (; copied-- > 0 ; crc = COMPUTE_FCS (crc, *os_buffer++ = *src++)); for (; (len-- > 0) && (CRC32_GOOD != crc); crc = COMPUTE_FCS (crc, *os_buffer++ = *src++)); trim = len + 4; if (CRC32_GOOD != crc) { TRACE_MSG1(NTT,"AAA frame: %03x", urb->framenum); THROW_IF(npd->seen_crc, crc_error); } else npd->seen_crc = 1; } //#else /* defined(CONFIG_OTG_NETWORK_BLAN_PADAFTER) */ #elif defined(CONFIG_OTG_NETWORK_BLAN_CRC) || defined(CONFIG_OTG_NETWORK_SAFE_CRC) /* * The CRC can be sent in two ways when the size of the transfer * ends up being a multiple of the packetsize: * * | * <data> <CRC><CRC><CRC><CRC>|<???> case 1 * <data> <NUL><CRC><CRC><CRC>|<CRC> case 2 * <data> <NUL><CRC><CRC><CRC><CRC>| case 3 * <data> <NUL><CRC><CRC><CRC>|<CRC> | case 4 * | * * This complicates CRC checking, there are four scenarios: * * 1. length is 1 more than multiple of packetsize with a trailing byte * 2. length is 1 more than multiple of packetsize * 3. length is multiple of packetsize * 4. none of the above * * Finally, even though we always compute CRC, we do not actually throw * things away until and unless we have previously seen a good CRC. * This allows backwards compatibility with hosts that do not support * adding a CRC to the frame. * */ // test if 1 more than packetsize multiple if (1 == (len % urb->wMaxPacketSize)) { u8 *cp = urb->buffer + len - 1 - 4; // copy and CRC up to the packetsize boundary crc = crc32_nocopy(urb->buffer, len - 1, CRC32_INIT); if (TRACE_VERBOSE) TRACE_MSG7(NTT,"A CRC nocopy: %08x %08x len: %d CRC: %02x %02x %02x %02x", CRC32_GOOD, crc, len, cp[0], cp[1], cp[2], cp[3]); // if the CRC is good then this is case 1 if (CRC32_GOOD != crc) { crc = crc32_nocopy(urb->buffer + len - 1, 1, crc); if (CRC32_GOOD != crc) { //crc_errors[len%64]++; TRACE_MSG3(NTT,"A CRC error %08x %08x %03x", CRC32_GOOD, crc, urb->framenum); printk(KERN_INFO"%s: A CRC\n", __FUNCTION__); npd->seen_crc_error = 1; THROW_IF(npd->seen_crc, crc_error); } else npd->seen_crc = 1; } else npd->seen_crc = 1; } else { u8 *cp = urb->buffer + len - 4; crc = crc32_nocopy(urb->buffer, len, CRC32_INIT); if (TRACE_VERBOSE) TRACE_MSG7(NTT,"B CRC nocopy: %08x %08x len: %d CRC: %02x %02x %02x %02x", CRC32_GOOD, crc, len, cp[0], cp[1], cp[2], cp[3]); if (CRC32_GOOD != crc) { //crc_errors[len%64]++; TRACE_MSG3(NTT,"B CRC error %08x %08x %03x", CRC32_GOOD, crc, urb->framenum); if (TRACE_VERBOSE) { TRACE_MSG2(NTT, "status: %d actual_length: %d", urb->status, urb->actual_length); TRACE_NRECV(NTT, 32, urb->buffer); TRACE_MSG0(NTT, "--"); TRACE_RECV(NTT, urb->actual_length, urb->buffer); } printk(KERN_INFO"%s: B CRC\n", __FUNCTION__); npd->seen_crc_error = 1; THROW_IF(npd->seen_crc, crc_error); } else npd->seen_crc = 1; // XXX shorten by 4 bytes? } // trim IFF we are paying attention to crc if (npd->seen_crc) trim = 4; #endif /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ if (net_fd_recv_buffer(function_instance, urb->buffer, len, os_data, crc_bad, trim)) { TRACE_MSG0(NTT, "FAILED"); net_os_dealloc_buffer(function_instance, os_data, os_buffer); } // catch a simple error, just increment missed error and general error CATCH(error) { //TRACE_MSG4(NTT,"CATCH(error) urb: %p status: %d len: %d function: %p", // urb, urb->status, urb->actual_length, function_instance); // catch a CRC error CATCH(crc_error) { crc_bad = 1; npd->seen_crc_error = 1; } } return 0; }
/*! net_fd_start_xmit_mdlm * @brief - start sending a buffer * * @param function_instance - function instance pointer * @param buffer * @param len * @param data * * @return: 0 if all OK * -EINVAL, -EUNATCH, -ENOMEM * rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above) * Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped. */ int net_fd_start_xmit_mdlm (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb = NULL; int rc; u32 crc; #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN int xmit_index = 0; int endpoint_index = BULK_IN_A; #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1])) ? 0 : 1; int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A; #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, xmit_index, usbd_high_speed(function_instance)); if (TRACE_VERBOSE) TRACE_MSG8(NTT,"npd: %p flags: %04x len: %d endpoint_index: %d " "xmit_index: %d xmit_started: %d %d in_pkt_sz: %d", npd, npd->flags, len, endpoint_index, xmit_index, otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1]), in_pkt_sz); #if defined(CONFIG_OTG_NETWORK_BLAN_CRC) || defined(CONFIG_OTG_NETWORK_SAFE_CRC) /* allocate urb 5 bytes larger than required */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); return -ENOMEM; } urb->actual_length = len; /* copy and crc len bytes */ crc = crc32_copy(urb->buffer, buffer, len, CRC32_INIT); if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz - 4)) { /* no longer in Kconfig - change undef to define to active padbyte */ #undef CONFIG_OTG_NETWORK_PADBYTE #ifdef CONFIG_OTG_NETWORK_PADBYTE // add a pad byte if required to ensure a short packet, usbdnet driver // will correctly handle pad byte before or after CRC, but the MCCI driver // wants it before the CRC. crc = crc32_pad(urb->buffer + urb->actual_length, 1, crc); urb->actual_length++; #else /* CONFIG_OTG_NETWORK_PADBYTE */ urb->flags |= USBD_URB_SENDZLP; TRACE_MSG2(NTT,"setting ZLP: urb: %p flags: %x", urb, urb->flags); #endif /* CONFIG_OTG_NETWORK_PADBYTE */ } crc = ~crc; urb->buffer[urb->actual_length++] = crc & 0xff; urb->buffer[urb->actual_length++] = (crc >> 8) & 0xff; urb->buffer[urb->actual_length++] = (crc >> 16) & 0xff; urb->buffer[urb->actual_length++] = (crc >> 24) & 0xff; #if defined(CONFIG_OTG_NETWORK_BLAN_FERMAT) if (npd->fermat) fermat_encode(urb->buffer, urb->actual_length); #endif #else /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ /* allocate urb with no buffer */ #ifdef CONFIG_OTG_NETWORK_XMIT_OS if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, 0, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); return -ENOMEM; } urb->actual_length = len; urb->buffer = buffer; #else /* CONFIG_OTG_NETWORK_XMIT_OS */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa); return -ENOMEM; } urb->actual_length = len; memcpy (urb->buffer, buffer, len); #endif /* CONFIG_OTG_NETWORK_XMIT_OS */ urb->flags |= ((urb->actual_length % in_pkt_sz) == 0) ? USBD_URB_SENDZLP : 0; #endif /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ if (TRACE_VERBOSE) TRACE_MSG3(NTT,"urb: %p buf: %p priv: %p", urb, data, urb->function_privdata); urb->function_privdata = data; otg_atomic_add(urb->actual_length, &npd->queued_bytes); otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]); if ((rc = usbd_start_in_urb (urb))) { TRACE_MSG1(NTT,"FAILED: %d", rc); printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc); urb->function_privdata = NULL; otg_atomic_sub(urb->actual_length, &npd->queued_bytes); otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]); usbd_free_urb (urb); return rc; } return 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); }