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

📄 m66592-udc.c

📁 linux下面gadget设备驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	disable_irq_empty(m66592, ep->pipenum);	pipe_start(m66592, ep->pipenum);	tmp = m66592_read(m66592, ep->fifoctr);	if (unlikely((tmp & M66592_FRDY) == 0))		pipe_irq_enable(m66592, ep->pipenum);	else		irq_packet_write(ep, req);}static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req){	struct m66592 *m66592 = ep->m66592;	u16 pipenum = ep->pipenum;	if (ep->pipenum == 0) {		m66592_mdfy(m66592, M66592_PIPE0,				(M66592_ISEL | M66592_CURPIPE),				M66592_CFIFOSEL);		m66592_write(m66592, M66592_BCLR, ep->fifoctr);		pipe_start(m66592, pipenum);		pipe_irq_enable(m66592, pipenum);	} else {		if (ep->use_dma) {			m66592_bset(m66592, M66592_TRCLR, ep->fifosel);			pipe_change(m66592, pipenum);			m66592_bset(m66592, M66592_TRENB, ep->fifosel);			m66592_write(m66592,				(req->req.length + ep->ep.maxpacket - 1)					/ ep->ep.maxpacket,				ep->fifotrn);		}		pipe_start(m66592, pipenum);	/* trigger once */		pipe_irq_enable(m66592, pipenum);	}}static void start_packet(struct m66592_ep *ep, struct m66592_request *req){	if (ep->desc->bEndpointAddress & USB_DIR_IN)		start_packet_write(ep, req);	else		start_packet_read(ep, req);}static void start_ep0(struct m66592_ep *ep, struct m66592_request *req){	u16 ctsq;	ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;	switch (ctsq) {	case M66592_CS_RDDS:		start_ep0_write(ep, req);		break;	case M66592_CS_WRDS:		start_packet_read(ep, req);		break;	case M66592_CS_WRND:		control_end(ep->m66592, 0);		break;	default:		printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);		break;	}}static void init_controller(struct m66592 *m66592){	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),			M66592_PINCFG);	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */	m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);	m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);	msleep(3);	m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);	msleep(1);	m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);	m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,			M66592_DMA0CFG);}static void disable_controller(struct m66592 *m66592){	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);	udelay(1);	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);	udelay(1);	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);	udelay(1);	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);}static void m66592_start_xclock(struct m66592 *m66592){	u16 tmp;	tmp = m66592_read(m66592, M66592_SYSCFG);	if (!(tmp & M66592_XCKE))		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);}/*-------------------------------------------------------------------------*/static void transfer_complete(struct m66592_ep *ep,		struct m66592_request *req, int status)__releases(m66592->lock)__acquires(m66592->lock){	int restart = 0;	if (unlikely(ep->pipenum == 0)) {		if (ep->internal_ccpl) {			ep->internal_ccpl = 0;			return;		}	}	list_del_init(&req->queue);	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)		req->req.status = -ESHUTDOWN;	else		req->req.status = status;	if (!list_empty(&ep->queue))		restart = 1;	spin_unlock(&ep->m66592->lock);	req->req.complete(&ep->ep, &req->req);	spin_lock(&ep->m66592->lock);	if (restart) {		req = list_entry(ep->queue.next, struct m66592_request, queue);		if (ep->desc)			start_packet(ep, req);	}}static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req){	int i;	u16 tmp;	unsigned bufsize;	size_t size;	void *buf;	u16 pipenum = ep->pipenum;	struct m66592 *m66592 = ep->m66592;	pipe_change(m66592, pipenum);	m66592_bset(m66592, M66592_ISEL, ep->fifosel);	i = 0;	do {		tmp = m66592_read(m66592, ep->fifoctr);		if (i++ > 100000) {			printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"				"conflict. please power off this controller.");			return;		}		ndelay(1);	} while ((tmp & M66592_FRDY) == 0);	/* prepare parameters */	bufsize = get_buffer_size(m66592, pipenum);	buf = req->req.buf + req->req.actual;	size = min(bufsize, req->req.length - req->req.actual);	/* write fifo */	if (req->req.buf) {		if (size > 0)			m66592_write_fifo(m66592, ep->fifoaddr, buf, size);		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);	}	/* update parameters */	req->req.actual += size;	/* check transfer finish */	if ((!req->req.zero && (req->req.actual == req->req.length))			|| (size % ep->ep.maxpacket)			|| (size == 0)) {		disable_irq_ready(m66592, pipenum);		disable_irq_empty(m66592, pipenum);	} else {		disable_irq_ready(m66592, pipenum);		enable_irq_empty(m66592, pipenum);	}	pipe_start(m66592, pipenum);}static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req){	u16 tmp;	unsigned bufsize;	size_t size;	void *buf;	u16 pipenum = ep->pipenum;	struct m66592 *m66592 = ep->m66592;	pipe_change(m66592, pipenum);	tmp = m66592_read(m66592, ep->fifoctr);	if (unlikely((tmp & M66592_FRDY) == 0)) {		pipe_stop(m66592, pipenum);		pipe_irq_disable(m66592, pipenum);		printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);		return;	}	/* prepare parameters */	bufsize = get_buffer_size(m66592, pipenum);	buf = req->req.buf + req->req.actual;	size = min(bufsize, req->req.length - req->req.actual);	/* write fifo */	if (req->req.buf) {		m66592_write_fifo(m66592, ep->fifoaddr, buf, size);		if ((size == 0)				|| ((size % ep->ep.maxpacket) != 0)				|| ((bufsize != ep->ep.maxpacket)					&& (bufsize > size)))			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);	}	/* update parameters */	req->req.actual += size;	/* check transfer finish */	if ((!req->req.zero && (req->req.actual == req->req.length))			|| (size % ep->ep.maxpacket)			|| (size == 0)) {		disable_irq_ready(m66592, pipenum);		enable_irq_empty(m66592, pipenum);	} else {		disable_irq_empty(m66592, pipenum);		pipe_irq_enable(m66592, pipenum);	}}static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req){	u16 tmp;	int rcv_len, bufsize, req_len;	int size;	void *buf;	u16 pipenum = ep->pipenum;	struct m66592 *m66592 = ep->m66592;	int finish = 0;	pipe_change(m66592, pipenum);	tmp = m66592_read(m66592, ep->fifoctr);	if (unlikely((tmp & M66592_FRDY) == 0)) {		req->req.status = -EPIPE;		pipe_stop(m66592, pipenum);		pipe_irq_disable(m66592, pipenum);		printk(KERN_ERR "read fifo not ready");		return;	}	/* prepare parameters */	rcv_len = tmp & M66592_DTLN;	bufsize = get_buffer_size(m66592, pipenum);	buf = req->req.buf + req->req.actual;	req_len = req->req.length - req->req.actual;	if (rcv_len < bufsize)		size = min(rcv_len, req_len);	else		size = min(bufsize, req_len);	/* update parameters */	req->req.actual += size;	/* check transfer finish */	if ((!req->req.zero && (req->req.actual == req->req.length))			|| (size % ep->ep.maxpacket)			|| (size == 0)) {		pipe_stop(m66592, pipenum);		pipe_irq_disable(m66592, pipenum);		finish = 1;	}	/* read fifo */	if (req->req.buf) {		if (size == 0)			m66592_write(m66592, M66592_BCLR, ep->fifoctr);		else			m66592_read_fifo(m66592, ep->fifoaddr, buf, size);	}	if ((ep->pipenum != 0) && finish)		transfer_complete(ep, req, 0);}static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb){	u16 check;	u16 pipenum;	struct m66592_ep *ep;	struct m66592_request *req;	if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {		m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);		m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,				M66592_CFIFOSEL);		ep = &m66592->ep[0];		req = list_entry(ep->queue.next, struct m66592_request, queue);		irq_packet_read(ep, req);	} else {		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {			check = 1 << pipenum;			if ((status & check) && (enb & check)) {				m66592_write(m66592, ~check, M66592_BRDYSTS);				ep = m66592->pipenum2ep[pipenum];				req = list_entry(ep->queue.next,						 struct m66592_request, queue);				if (ep->desc->bEndpointAddress & USB_DIR_IN)					irq_packet_write(ep, req);				else					irq_packet_read(ep, req);			}		}	}}static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb){	u16 tmp;	u16 check;	u16 pipenum;	struct m66592_ep *ep;	struct m66592_request *req;	if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);		ep = &m66592->ep[0];		req = list_entry(ep->queue.next, struct m66592_request, queue);		irq_ep0_write(ep, req);	} else {		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {			check = 1 << pipenum;			if ((status & check) && (enb & check)) {				m66592_write(m66592, ~check, M66592_BEMPSTS);				tmp = control_reg_get(m66592, pipenum);				if ((tmp & M66592_INBUFM) == 0) {					disable_irq_empty(m66592, pipenum);					pipe_irq_disable(m66592, pipenum);					pipe_stop(m66592, pipenum);					ep = m66592->pipenum2ep[pipenum];					req = list_entry(ep->queue.next,							 struct m66592_request,							 queue);					if (!list_empty(&ep->queue))						transfer_complete(ep, req, 0);				}			}		}	}}static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)__releases(m66592->lock)__acquires(m66592->lock){	struct m66592_ep *ep;	u16 pid;	u16 status = 0;	u16 w_index = le16_to_cpu(ctrl->wIndex);	switch (ctrl->bRequestType & USB_RECIP_MASK) {	case USB_RECIP_DEVICE:		status = 1 << USB_DEVICE_SELF_POWERED;		break;	case USB_RECIP_INTERFACE:		status = 0;		break;	case USB_RECIP_ENDPOINT:		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];		pid = control_reg_get_pid(m66592, ep->pipenum);		if (pid == M66592_PID_STALL)			status = 1 << USB_ENDPOINT_HALT;		else			status = 0;		break;	default:		pipe_stall(m66592, 0);		return;		/* exit */	}	m66592->ep0_data = cpu_to_le16(status);	m66592->ep0_req->buf = &m66592->ep0_data;	m66592->ep0_req->length = 2;	/* AV: what happens if we get called again before that gets through? */	spin_unlock(&m66592->lock);	m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);	spin_lock(&m66592->lock);}static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl){	switch (ctrl->bRequestType & USB_RECIP_MASK) {	case USB_RECIP_DEVICE:		control_end(m66592, 1);		break;	case USB_RECIP_INTERFACE:		control_end(m66592, 1);		break;	case USB_RECIP_ENDPOINT: {		struct m66592_ep *ep;		struct m66592_request *req;		u16 w_index = le16_to_cpu(ctrl->wIndex);		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];		pipe_stop(m66592, ep->pipenum);		control_reg_sqclr(m66592, ep->pipenum);		control_end(m66592, 1);		req = list_entry(ep->queue.next,		struct m66592_request, queue);		if (ep->busy) {			ep->busy = 0;			if (list_empty(&ep->queue))				break;			start_packet(ep, req);		} else if (!list_empty(&ep->queue))			pipe_start(m66592, ep->pipenum);		}		break;	default:		pipe_stall(m66592, 0);		break;	}}static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl){	switch (ctrl->bRequestType & USB_RECIP_MASK) {	case USB_RECIP_DEVICE:		control_end(m66592, 1);		break;	case USB_RECIP_INTERFACE:		control_end(m66592, 1);		break;	case USB_RECIP_ENDPOINT: {		struct m66592_ep *ep;		u16 w_index = le16_to_cpu(ctrl->wIndex);		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];		pipe_stall(m66592, ep->pipenum);		control_end(m66592, 1);		}		break;	default:		pipe_stall(m66592, 0);		break;	}}/* if return value is true, call class driver's setup() */static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl){	u16 *p = (u16 *)ctrl;	unsigned long offset = M66592_USBREQ;	int i, ret = 0;	/* read fifo */	m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);	for (i = 0; i < 4; i++)		p[i] = m66592_read(m66592, offset + i*2);	/* check request */	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {		switch (ctrl->bRequest) {		case USB_REQ_GET_STATUS:			get_status(m66592, ctrl);			break;		case USB_REQ_CLEAR_FEATURE:			clear_feature(m66592, ctrl);			break;		case USB_REQ_SET_FEATURE:			set_feature(m66592, ctrl);			break;		default:			ret = 1;			break;		}	} else		ret = 1;	return ret;}static void m66592_update_usb_speed(struct m66592 *m66592){	u16 speed = get_usb_speed(m66592);	switch (speed) {	case M66592_HSMODE:		m66592->gadget.speed = USB_SPEED_HIGH;		break;	case M66592_FSMODE:		m66592->gadget.speed = USB_SPEED_FULL;		break;	default:		m66592->gadget.speed = USB_SPEED_UNKNOWN;		printk(KERN_ERR "USB speed unknown\n");	}}static void irq_device_state(struct m66592 *m66592){	u16 dvsq;	dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;	m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);	if (dvsq == M66592_DS_DFLT) {	/* bus reset */		m66592->driver->disconnect(&m66592->gadget);		m66592_update_usb_speed(m66592);	}	if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)		m66592_update_usb_speed(m66592);	if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)			&& m66592->gadget.speed == USB_SPEED_UNKNOWN)		m66592_update_usb_speed(m66592);	m66592->old_dvsq = dvsq;}static void irq_control_stage(struct m66592 *m66592)

⌨️ 快捷键说明

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