⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_pdc.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		if(pipe->ep_state == PDC_PIPE_OPEN) {
			pipe->pipe_desc =  NULL;
			pipe->ep_state = PDC_PIPE_CONFIG;
		}

		/* 
		 * Get the endpoint and if it is control ep then close
		 * the control IN pipe also
		 */
   		ep = pdc_pipe_to_epreg(pipe_handle); 

		if(ep == 0) {
			pdc_close_pipe(pipe_handle + 1);
		}
	}
} /* End of pdc_close_pipe() */

int pdc_submit_control_urb(struct pdc_dev	*pdc, struct pdc_urb *urb_req)
{
	struct pdc_pipe	*pipe;
	struct pdc_urb	*urb;
	unsigned long	length;
	pdc_pipe_handle_t	handle = urb_req->pipe;

	func_debug(("pdc_submit_control_urb(urb=%p)\n",urb_req))

	
	if(urb_req->operation == PDC_OPR_WRITE) handle += 1;	/* Control IN pipe */

	pipe = pdc->ep_pipes + handle;

	urb = pipe->urb;

	/* Insert the URB in to the pipe URB queue (FIFO) */
	if(!urb) {
		pipe->urb  = urb_req;
	} else {
		while(urb) {
			if(urb->next != NULL)	urb = urb->next;
			else urb->next = urb_req;
		}
	}

	/* set the output parameters */
	urb_req->actual_length = 0;
	urb_req->next = NULL;

	if(urb_req->operation == PDC_OPR_WRITE) {

		if(pipe->urb == urb_req)	{
			length = urb_req->transfer_buffer_length;
			if(urb_req->transfer_buffer_length > pipe->ep_desc->max_pkt_size) {
				length = pipe->ep_desc->max_pkt_size;
			}
			writeendpoint(handle,urb_req->transfer_buffer,length);
			urb_req->actual_length += length;
		}

		if(urb_req->actual_length == urb_req->transfer_buffer_length) {
			urb_req->status = PDC_URB_COMPLETE;
			pipe->urb = urb_req->next;
			if(urb_req->complete) urb_req->complete(urb);
		}

	} else if(urb_req->operation == PDC_OPR_READ) {
		/* TODO */
	}

	return 0;
}

/*
 * Submit an urb for data transfer
 * @urb: urb request block
 */
int pdc_submit_urb(struct pdc_urb *urb_req)
{
	struct pdc_pipe	*pipe;
	struct pdc_urb	*urb;
	unsigned long flags;
    struct pdc_dev 		*pdc=usb_devices;

	func_debug(("pdc_submit_urb(urb=%p)\n",urb_req))

	if(urb_req->pipe > PDC_MAX_PIPES)	return -EINVAL;

	if(urb_req->pipe < 2)	return pdc_submit_control_urb(pdc, urb_req);

	pipe = pdc->ep_pipes + urb_req->pipe;

	spin_lock_irqsave(&pdc_rdwr_lock, flags);

	urb = pipe->urb;

	/* Insert the URB in to the pipe URB queue (FIFO) */
	if(!urb) {
		pipe->urb  = urb_req;
	} else {
		while(urb) {
			if(urb->next != NULL)	urb = urb->next;
			else urb->next = urb_req;
		}
	}

	/* set the output parameters */
	urb_req->actual_length = 0;
	urb_req->next = NULL;

	if(urb_req->operation == PDC_OPR_READ) {

		/* 
		 * handle the read request, if there are no URB's,
		 * call the rx_data function 
		 */
		if(pipe->urb == urb_req)	{
			rx_data(pdc, urb_req->pipe);
		}

	} else if(urb_req->operation == PDC_OPR_WRITE) {

		/*
		 * Handle the write request.
		 * If the Pipe is not stalled and the transmission is idle
		 * start the transmission
		 */
		pipe->ep_status = (pdc_read16(CMD_CHECKEPSTATUS+(urb_req->pipe)) & STATUS_EPSTAL) ? PDC_PIPE_STALL : PDC_PIPE_UNSTALL ;

		if(pipe->txrx_idle && pipe->ep_status != PDC_PIPE_STALL) {
			tx_data(pdc, urb_req->pipe, 1);	/* Kick the transfer */
		}

	}

	spin_unlock_irqrestore(&pdc_rdwr_lock, flags);

	return 0;
} /* End of pdc_submit_urb */

/*
 * Cancel an urb for data transfer
 * @urb: urb request block
 */
int pdc_cancel_urb(struct pdc_urb *urb_req)
{
	struct pdc_pipe	*pipe;
	struct pdc_urb	*urb, *prev_urb;
	unsigned long flags;
    struct pdc_dev 		*pdc=usb_devices;

	func_debug(("pdc_cancel_urb(%p)\n",urb_req))

	/* Check the pipe value */
	if(urb_req->pipe > PDC_MAX_PIPES)	return -EINVAL;

	pipe = pdc->ep_pipes + urb_req->pipe;

	if((urb_req->pipe == 0) && (urb_req->operation == PDC_OPR_WRITE)) {
		/* Special case of control IN pipe */
		pipe++;
	}

	spin_lock_irqsave(&pdc_rdwr_lock, flags);

	prev_urb = NULL;
	urb = pipe->urb;

	/* 
	 * search for the URB , The pipe could be either IN or OUT so there is
	 * only one URB list 
	 */
	while((urb!=NULL) && (urb_req != urb)) {
		prev_urb = urb;
		urb = urb->next;
	}

	/* 
	 * found URB, then Un link it from the list
	 */
	if(urb) {
		urb->status = PDC_URB_COMPLETE;
		if(prev_urb)	prev_urb->next = urb->next;
		else pipe->urb = urb->next;
	}

	spin_unlock_irqrestore(&pdc_rdwr_lock, flags);

	return 0;
} /* End of pdc_cancel_urb */

/*
 * Pipe operations
 * @pipe_opr:
 */
int pdc_pipe_operation(struct pdc_pipe_opr   *pipe_opr)
{
	struct pdc_pipe	*pipe;
	__u16	status;
    struct pdc_dev 		*pdc=usb_devices;
	pdc_pipe_handle_t	handle = pipe_opr->handle;


	func_debug(("pdc_pipe_control(pipe_opr=%p)\n",pipe_opr))

	if(handle < PDC_MAX_PIPES) {

		pipe = pdc->ep_pipes + handle;
	
		switch(pipe_opr->opr) {

			case PDC_PIPE_STALL:

				pdc_command(CMD_STALLEP+handle);

				if(handle == EP0OUT) pdc_command(CMD_STALLEP+handle+1);	/* Stall control in also */
			
				break;

			case PDC_PIPE_UNSTALL:

				pdc_command(CMD_UNSTALLEP+handle);
				if(handle == EP0OUT) pdc_command(CMD_UNSTALLEP+handle+1);	/* untall control in also */

			 	if(handle > EP0IN) {
					if(pipe->ep_desc->ep_dir & PDC_EP_DIR_IN)
						tx_data(pdc, handle, 2);
					else 
						rx_data(pdc, handle);
				}
				break;

			case PDC_GET_PIPE_STATUS:

				status = pdc_read16(CMD_READEPSTATUS+handle);
				pipe_opr->pipe_status = (status&STATUS_EPSTAL) ? PDC_PIPE_STALL :PDC_PIPE_UNSTALL; 

				break;
		}

		return 0;
	}

	return -1;
} /* End of pdc_pipe_operation() */

/*--------------------------------------------------------------*
 *          Device Controller intialization functions
 *--------------------------------------------------------------*/
/* Initialisation of the Peripheral Controller */
void pdc_init(struct isp1362_dev	*dev)
{

	func_debug(("pdc_init(dev=%p)\n",dev))

	/* set the ISP1362 Device controller Hardware Configuration */
	isp1362_set_hw_config(dev);

	/* Set DMA mode (no dma) */
	pdc_write16(CMD_WRITEDMACONFIG,0);

	/*bledia Disable all interrupts */
	pdc_write32(CMD_WRITEIRQENABLE,0);

	/* Set default address */
	pdc_write16(CMD_WRITEADDRESS,0);
	
	return;
} /* End of pdc_init */




/* Actually connect to the bus */
void pdc_connect(void)
{
	/* Set device address & enable */
	pdc_write16(CMD_WRITEADDRESS,ADDRESS_DEVEN|0);

	/* Enable interrupts */
	pdc_write32(CMD_WRITEIRQENABLE,IE_EP0OUT|IE_EP0IN|IE_RST|IE_SUSP);

	/* Connect to the bus */
	pdc_write16(CMD_WRITEMODE,MODE_SOFTCT|MODE_INTENA);

	return;

} /* End of pdc_connect */


/*---------------------------------------------------------------------*
 *                   ISP1362 HOSAL interface functions                 *
 *---------------------------------------------------------------------*/
struct isp1362_driver	pdc_driver = {
	name:		"usb-pdc",
	index:		ISP1362_DC,
	probe:		pdc_probe,
	remove:		pdc_remove,
};

/* Device initialisation */
int pdc_probe (struct isp1362_dev	*dev) 
{
    struct pdc_dev *pdc=usb_devices;
	int result, i;
	struct pdc_pipe	*pipe;

	func_debug(("pdc_probe(dev=%p)\n",dev))

	/* Grab the IO resources */
	result = isp1362_check_io_region(dev);

	if(result < 0) {
		detail_debug(("%s IO resources are not free\n","isp1362-pdc"))
		return result;
	}

	isp1362_request_io_region(dev);

	pdc->dev = dev;
	isp1362_dc_dev = dev;


	for(i=0; i< PDC_MAX_PIPES;i++) {
		pipe = pdc->ep_pipes + i;

		pipe->urb = NULL;
		pipe->txrx_idle = 1;
		pipe->ep_state = PDC_PIPE_UNCONFIG;
		pipe->ep_desc = NULL;
	}



	/* Configure the default end points */
	/* Configure the control OUT pipe */
	pipe = pdc->ep_pipes;
	pipe->ep_desc = &pdc_ctrl_ep_desc[0];

	pipe->ep_desc->ep_num = 0;
	pipe->ep_desc->ep_dir = PDC_EP_DIR_OUT;
	pipe->ep_desc->attributes = PDC_EP_CONTROL;
	pipe->ep_desc->max_pkt_size = 64;
	pipe->ep_state = PDC_PIPE_CONFIG;

	/* configure the control IN pipe */
	pipe = pdc->ep_pipes + 1;
	pipe->ep_desc = &pdc_ctrl_ep_desc[1];

	pipe->ep_desc->ep_num = 0;
	pipe->ep_desc->ep_dir = PDC_EP_DIR_IN;
	pipe->ep_desc->attributes = PDC_EP_CONTROL;
	pipe->ep_desc->max_pkt_size = 64;
	pipe->ep_state = PDC_PIPE_CONFIG;

	pdc_bus_init(pdc);

	/* Do chip setup */
	pdc_init(dev);

	/* Claim USB IRQ */
	result=isp1362_request_irq(pdc_isr,dev,pdc);

	/* Got it ok? */
	if (result < 0) {
		detail_debug((KERN_ERR "usb-pdc:Can't get USB device IRQ %d.\n", dev->irq))
		return result;
	}

	detail_debug(("usb-pdc:device IRQ is initialised, Irq is  %04x\n",dev->irq))

	/* If there are pending IRQs, process them as we can only
	   detect edges */

#ifndef CONFIG_USB_OTG
	/* All ready! */
	pdc_connect();
#endif /* CONFIG_USB_OTG */

	dev->driver_data = pdc;

	detail_debug(("pdc:Philips USB device driver in INIT.\n"))

	return 0;

} /* End of pdc_probe */


void pdc_remove (struct isp1362_dev	*dev) 
{
    struct pdc_dev *pdc=(struct pdc_dev*)dev->driver_data;

	func_debug(("pdc_remove(dev=%p)\n",dev))

	pdc_bus_deinit();

	/* Go off bus */
	pdc_write16(CMD_WRITEADDRESS,0);

	/* Turn off IRQs */
	pdc_write32(CMD_WRITEIRQENABLE,0);

	/* Global IRQ disable & turn off softconnect */
	pdc_write16(CMD_WRITEMODE,0);

	/* Free IRQ */
	isp1362_free_irq(dev,pdc);

	isp1362_release_io_region(dev);	/* release IO space */

	pdc->dev = NULL;
	isp1362_dc_dev = NULL;
	pdc->ep_pipes = pdc_eps;

} /* End of pdc_remove */

/*
 * This is module init function
 * This function registers the PDC driver to ISP1362 HOSAL driver
 * which in turn calls the probe function when the dev is found
 */
static int __init pdc_module_init (void) 
{
	struct pdc_dev  *pdc = usb_devices;
	int	result;

	func_debug(("pdc_module_init(void)\n"))

	pdc->dev = NULL;
	pdc->ep_pipes = pdc_eps;
	isp1362_dc_dev = NULL;

	result = isp1362_register_driver(&pdc_driver);

	if(result == 0) {
		isp1362_printk(KERN_INFO __FILE__ ": %s Initialization Success \n",pdc_driver.name);
	} else {
		isp1362_printk(KERN_INFO __FILE__ ": %s Iinitialization Failed (error = %d)\n",pdc_driver.name,result);
	}

	return  result;
} /* End of pdc_module_init */

/*
 * This is module cleanup function
 * Unregister from isp1362 HOSAL layer which in turn calls 
 * Close function
 */
static void __exit pdc_module_cleanup (void) 
{
	
	func_debug(("pdc_module_cleanup (void)\n"))

	return isp1362_unregister_driver(&pdc_driver);

} /* End of pdc_module_cleanup */

module_init (pdc_module_init);
module_exit (pdc_module_cleanup);

MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -