예제 #1
0
/*!
 * 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;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
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
 */
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;
}
예제 #6
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
}
예제 #7
0
/*!
 * 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;
}
예제 #8
0
/*! 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;
}
예제 #9
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);
}
예제 #10
0
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;
}
예제 #11
0
/*! 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);
}
예제 #12
0
/*! 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;
}
예제 #13
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);
        }

}
예제 #14
0
/*!
 * 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;
        }
} 
예제 #15
0
/*!
 * @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);
}
예제 #16
0
/*! 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;
        }
예제 #17
0
/*! 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 ();
}
예제 #18
0
/*!
 * 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;
}
예제 #19
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;
}
예제 #20
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;
}
예제 #21
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);
}