m66592-udc.c revision 7eff1d83a3b846d16a4cd706d06b5827a07c08a3
14cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*
24cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * M66592 UDC (USB gadget)
34cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
44cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * Copyright (C) 2006-2007 Renesas Solutions Corp.
54cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
65db05c09ac107ef957b7a052d7bba8190c93b460Yoshihiro Shimoda * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
74cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
84cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * This program is free software; you can redistribute it and/or modify
94cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * it under the terms of the GNU General Public License as published by
104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * the Free Software Foundation; version 2 of the License.
114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * This program is distributed in the hope that it will be useful,
134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * but WITHOUT ANY WARRANTY; without even the implied warranty of
144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * GNU General Public License for more details.
164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * You should have received a copy of the GNU General Public License
184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * along with this program; if not, write to the Free Software
194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda */
224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/module.h>
244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/interrupt.h>
25598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda#include <linux/delay.h>
26598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda#include <linux/io.h>
274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/platform_device.h>
285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
2956fd1260a8de3738034588c6e32262960c5b2660Paul Mundt#include <linux/err.h>
304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/usb/ch9.h>
319454a57ab5922e5cd25321cae9d1a8cbeb3e2e85David Brownell#include <linux/usb/gadget.h>
324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include "m66592-udc.h"
344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
35598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_DESCRIPTION("M66592 USB gadget driver");
364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaMODULE_LICENSE("GPL");
374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaMODULE_AUTHOR("Yoshihiro Shimoda");
38f34c32f13ce8c539f3f582562358e39a86b00e83Kay SieversMODULE_ALIAS("platform:m66592_udc");
394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
402c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#define DRIVER_VERSION	"21 July 2009"
414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char udc_name[] = "m66592_udc";
434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char *m66592_ep_name[] = {
444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	"ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592);
484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags);
524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
54598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status);
55598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 get_usb_speed(struct m66592 *m66592)
584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
63598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
69598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, (1 << pipenum), reg);
714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
75598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
81598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, (1 << pipenum), reg);
834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_connect(struct m66592 *m66592)
874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
90598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_disconnect(struct m66592 *m66592)
97598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
98598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
1014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
102598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
1034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
1044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
1054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.speed = USB_SPEED_UNKNOWN;
1074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock(&m66592->lock);
1084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver->disconnect(&m66592->gadget);
1094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock(&m66592->lock);
1104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
1124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->ep[0].queue);
1134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
1164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid = 0;
1184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
1224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, offset) & M66592_PID;
1254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
12600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return pid;
1294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
132598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pid)
1334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
1384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, offset);
1414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
14200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_start(struct m66592 *m66592, u16 pipenum)
1464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
1484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
1514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
1534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
1564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
1584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
1614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ret = 0;
1634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, M66592_DCPCTR);
1674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, offset);
1704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
17100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
1744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
1774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_stop(m66592, pipenum);
1814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
1844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, offset);
1874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
18800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num(%d)\n", pipenum);
1894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
1924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
1944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
1954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0) {
1974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_DCPCFG);
1984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0)
1994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = 256;
2004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else {
2014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_DCPMAXP);
2024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MAXP;
2034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
2054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, pipenum, M66592_PIPESEL);
2064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_PIPECFG);
2074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0) {
2084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEBUF);
2094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = ((tmp >> 10) + 1) * 64;
2104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
2114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEMAXP);
2124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MXPS;
2134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return size;
2174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_change(struct m66592 *m66592, u16 pipenum)
2204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
2222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned short mbw;
2234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
2254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
2284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ndelay(450);
2304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip)
2322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		mbw = M66592_MBW_32;
2332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	else
2342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		mbw = M66592_MBW_16;
2352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
2362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592_bset(m66592, mbw, ep->fifosel);
2374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int pipe_buffer_setting(struct m66592 *m66592,
240598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_pipe_info *info)
2414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 bufnum = 0, buf_bsize = 0;
2434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipecfg = 0;
2444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
2474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->pipe, M66592_PIPESEL);
2494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->dir_in)
2514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DIR;
2524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->type;
2534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->epnum;
2544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (info->type) {
2554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_INT:
2564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
2574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 0;
2584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_BULK:
2604048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		/* isochronous pipes may be used as bulk pipes */
261108be95f9ffc53660c9a35b5ceef94121b1e23c4Yusuke Goda		if (info->pipe >= M66592_BASE_PIPENUM_BULK)
2624048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm			bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
2634048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		else
2644048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm			bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
2654048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm
2664048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
2674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DBLB;
2694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (!info->dir_in)
2704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipecfg |= M66592_SHTNAK;
2714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_ISO:
2734048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		bufnum = M66592_BASE_BUFNUM +
2744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
2754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2784048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm
2794048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm	if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
2804048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		pr_err("m66592 pipe memory is insufficient\n");
2814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENOMEM;
2824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, pipecfg, M66592_PIPECFG);
2854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
2864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
2874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->interval)
2884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info->interval--;
2894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->interval, M66592_PIPEPERI);
2904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
2924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_buffer_release(struct m66592 *m66592,
2954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				struct m66592_pipe_info *info)
2964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (is_bulk_pipe(info->pipe)) {
3014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk--;
3024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else if (is_interrupt_pipe(info->pipe))
3034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->interrupt--;
3044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (is_isoc_pipe(info->pipe)) {
3054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->isochronous--;
3064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (info->type == M66592_BULK)
3074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->bulk--;
3084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
30900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ep_release: unexpect pipenum (%d)\n",
310598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info->pipe);
3114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_initialize(struct m66592_ep *ep)
3144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3162c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned short mbw;
3174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
3194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_ACLRM, ep->pipectr);
3214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, 0, ep->pipectr);
3224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_SQCLR, ep->pipectr);
3234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma) {
3244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
3254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(450);
3274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3282c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->on_chip)
3292c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			mbw = M66592_MBW_32;
3302c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
3312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			mbw = M66592_MBW_16;
3322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
3332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, mbw, ep->fifosel);
3344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
338598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc,
339598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pipenum, int dma)
3404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((pipenum != 0) && dma) {
3424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->num_dma == 0) {
3434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D0FIFO;
3464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D0FIFOSEL;
3474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D0FIFOCTR;
3484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D0FIFOTRN;
3492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		} else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
3504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D1FIFO;
3534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D1FIFOSEL;
3544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D1FIFOCTR;
3554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D1FIFOTRN;
3564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
3574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 0;
3584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_CFIFO;
3594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_CFIFOSEL;
3604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_CFIFOCTR;
3614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = 0;
3624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
3634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
3644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->use_dma = 0;
3654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoaddr = M66592_CFIFO;
3664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifosel = M66592_CFIFOSEL;
3674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoctr = M66592_CFIFOCTR;
3684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifotrn = 0;
3694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipectr = get_pipectr_addr(pipenum);
3724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = pipenum;
373598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
3744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[pipenum] = ep;
3754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
3764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&ep->queue);
3774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_release(struct m66592_ep *ep)
3804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
3834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
3854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
3864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
3884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->num_dma--;
3894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = 0;
3904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->busy = 0;
3914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->use_dma = 0;
3924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int alloc_pipe_config(struct m66592_ep *ep,
395598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc)
3964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
3994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int dma = 0;
4004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int *counter;
4014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret;
4024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->desc = desc;
4044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(ep->pipenum);
4064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
407598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
4084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_BULK:
4094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
4104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
41100274921a052d3232d9f00856387fb269ac0af11David Brownell				pr_err("bulk pipe is insufficient\n");
4124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				return -ENODEV;
4134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
414598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info.pipe = M66592_BASE_PIPENUM_ISOC
415598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda						+ m66592->isochronous;
4164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				counter = &m66592->isochronous;
4174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
4184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
4194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
4204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			counter = &m66592->bulk;
4214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_BULK;
4234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		dma = 1;
4244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_INT:
4264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
42700274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("interrupt pipe is insufficient\n");
4284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
4314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_INT;
4324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->interrupt;
4334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_ISOC:
4354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
43600274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("isochronous pipe is insufficient\n");
4374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
4404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_ISO;
4414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->isochronous;
4424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
44400274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect xfer type\n");
4454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
4464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->type = info.type;
4484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
450598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
4514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.interval = desc->bInterval;
4524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
4534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 1;
4544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
4554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 0;
4564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ret = pipe_buffer_setting(m66592, &info);
4584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
45900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("pipe_buffer_setting fail\n");
4604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return ret;
4614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	(*counter)++;
4644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
4654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk++;
4664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
4684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_initialize(ep);
4694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int free_pipe_config(struct m66592_ep *ep)
4744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
4764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
4774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.pipe = ep->pipenum;
4794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.type = ep->type;
4804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_buffer_release(m66592, &info);
4814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_release(ep);
4824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
4874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
4884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_ready(m66592, pipenum);
4904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_nrdy(m66592, pipenum);
4914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
4944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_ready(m66592, pipenum);
4964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_nrdy(m66592, pipenum);
4974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if complete is true, gadget driver complete function is not call */
5004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void control_end(struct m66592 *m66592, unsigned ccpl)
5014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].internal_ccpl = ccpl;
5034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, 0);
5044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
5054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
5084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
513598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			(M66592_ISEL | M66592_CURPIPE),
514598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_CFIFOSEL);
5154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.length == 0) {
5174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
5184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, 0);
5194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
5204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
5224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
5234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
5274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
5304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_empty(m66592, ep->pipenum);
5334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, ep->pipenum);
5344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
5364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0))
5374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, ep->pipenum);
5384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_write(ep, req);
5404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
5434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
5464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->pipenum == 0) {
5484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0,
549598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(M66592_ISEL | M66592_CURPIPE),
550598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
5514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);
5534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->use_dma) {
5564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
5574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_change(m66592, pipenum);
5584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRENB, ep->fifosel);
5594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592,
560598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(req->req.length + ep->ep.maxpacket - 1)
561598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					/ ep->ep.maxpacket,
562598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				ep->fifotrn);
5634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
5644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);	/* trigger once */
5654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet(struct m66592_ep *ep, struct m66592_request *req)
5704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->desc->bEndpointAddress & USB_DIR_IN)
5724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_write(ep, req);
5734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
5784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
5804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
5824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
5844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
5854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0_write(ep, req);
5864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
5884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
5924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(ep->m66592, 0);
5934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
59500274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
5964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6008c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimodastatic void init_controller(struct m66592 *m66592)
6018c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda{
6022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned int endian;
6038c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6042c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
6052c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->endian)
6062c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = 0; /* big endian */
6072c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6082c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = M66592_LITTLE; /* little endian */
6098c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
6112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6132c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6148c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6152c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		/* This is a workaound for SH7722 2nd cut */
6162c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
6172c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, 0x1000, M66592_TESTMODE);
6182c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
6194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6202c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
6212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, 0, M66592_CFBCFG);
6232c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, 0, M66592_D0FBCFG);
6242c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, endian, M66592_CFBCFG);
6252c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, endian, M66592_D0FBCFG);
6262c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	} else {
6272c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		unsigned int clock, vif, irq_sense;
6282c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6292c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->endian)
6302c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = M66592_BIGEND; /* big endian */
6312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = 0; /* little endian */
6332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->vif)
6352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			vif = M66592_LDRV; /* 3.3v */
6362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6372c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			vif = 0; /* 1.5v */
6382c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6392c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		switch (m66592->pdata->xtal) {
6402c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_12MHZ:
6412c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL12;
6422c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6432c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_24MHZ:
6442c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL24;
6452c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6462c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_48MHZ:
6472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL48;
6482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		default:
6502c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			pr_warning("m66592-udc: xtal configuration error\n");
6512c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = 0;
6522c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
6534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6542c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		switch (m66592->irq_trigger) {
6552c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case IRQF_TRIGGER_LOW:
6562c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = M66592_INTL;
6572c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6582c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case IRQF_TRIGGER_FALLING:
6592c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = 0;
6602c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6612c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		default:
6622c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			pr_warning("m66592-udc: irq trigger config error\n");
6632c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = 0;
6642c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
6654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6662c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592,
6672c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    (vif & M66592_LDRV) | (endian & M66592_BIGEND),
6682c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    M66592_PINCFG);
6692c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
6702c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
6712c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    M66592_SYSCFG);
6722c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6732c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6742c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6762c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
6772c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6782c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		msleep(3);
6794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6802c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
6814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6822c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		msleep(1);
6834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6842c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
6852c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6862c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
6872c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
6882c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			     M66592_DMA0CFG);
6892c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
6904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592)
6934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
694ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda	m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
6952c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!m66592->pdata->on_chip) {
6962c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
6972c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
6982c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
6992c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
7002c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
7012c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
7022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
7032c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
7044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_start_xclock(struct m66592 *m66592)
7074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
7094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!m66592->pdata->on_chip) {
7112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		tmp = m66592_read(m66592, M66592_SYSCFG);
7122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (!(tmp & M66592_XCKE))
7132c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
7142c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
7154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
7184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
719598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status)
720598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
721598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
7224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int restart = 0;
7244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely(ep->pipenum == 0)) {
7264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->internal_ccpl) {
7274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->internal_ccpl = 0;
7284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_del_init(&req->queue);
7334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
7344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -ESHUTDOWN;
7354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
7364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = status;
7374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
7394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		restart = 1;
7404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
741598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&ep->m66592->lock);
742598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	req->req.complete(&ep->ep, &req->req);
743598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&ep->m66592->lock);
7444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (restart) {
7464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
7474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->desc)
7484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
7494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
7534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
755598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 tmp;
7564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
7574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
7584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
7594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
7604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
7614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
7634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_ISEL, ep->fifosel);
7644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	i = 0;
7664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	do {
7674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, ep->fifoctr);
7684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i++ > 100000) {
76900274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("pipe0 is busy. maybe cpu i/o bus "
7704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				"conflict. please power off this controller.");
7714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(1);
7744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} while ((tmp & M66592_FRDY) == 0);
7754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
7774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
7784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
7794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
7804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
7824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
7834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size > 0)
784bb59dbff4e5fb0ac14e3ee47d3f688490f128155Yoshihiro Shimoda			m66592_write_fifo(m66592, ep, buf, size);
7854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
7864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
7874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
7904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
7914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
793598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
794598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
795598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
7964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
7984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
7994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
8004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
8014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, pipenum);
8034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
8064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
8084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
8094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
8104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
81900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("write fifo not ready. pipnum=%d\n", pipenum);
8204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
8274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
8294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
830bb59dbff4e5fb0ac14e3ee47d3f688490f128155Yoshihiro Shimoda		m66592_write_fifo(m66592, ep, buf, size);
831598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((size == 0)
832598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((size % ep->ep.maxpacket) != 0)
833598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((bufsize != ep->ep.maxpacket)
834598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&& (bufsize > size)))
8354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
8364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
841598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
842598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
843598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
8454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
8464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
8474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
8484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
8494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
8534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
8554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int rcv_len, bufsize, req_len;
8564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
8574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int finish = 0;
8614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -EPIPE;
8664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
86800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("read fifo not ready");
8694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	rcv_len = tmp & M66592_DTLN;
8744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req_len = req->req.length - req->req.actual;
8784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (rcv_len < bufsize)
8794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(rcv_len, req_len);
8804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
8814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(bufsize, req_len);
8824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
887598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
888598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
889598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
8924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		finish = 1;
8934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
8964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
8974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size == 0)
8984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592, M66592_BCLR, ep->fifoctr);
8994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
9004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
9014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ep->pipenum != 0) && finish)
9044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
9054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
9084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
9154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
9164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
917598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
9184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_read(ep, req);
9224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BRDYSTS);
9274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				ep = m66592->pipenum2ep[pipenum];
9284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				req = list_entry(ep->queue.next,
9294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						 struct m66592_request, queue);
9304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (ep->desc->bEndpointAddress & USB_DIR_IN)
9314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_write(ep, req);
9324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
9334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_read(ep, req);
9344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
9404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
9424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
9484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
9494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
9534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BEMPSTS);
9584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				tmp = control_reg_get(m66592, pipenum);
9594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if ((tmp & M66592_INBUFM) == 0) {
9604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					disable_irq_empty(m66592, pipenum);
9614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_irq_disable(m66592, pipenum);
9624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_stop(m66592, pipenum);
9634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					ep = m66592->pipenum2ep[pipenum];
9644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					req = list_entry(ep->queue.next,
9654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 struct m66592_request,
9664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 queue);
9674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					if (!list_empty(&ep->queue))
9684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						transfer_complete(ep, req, 0);
9694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				}
9704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
976598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
977598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
9784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid;
9814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 status = 0;
982598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 w_index = le16_to_cpu(ctrl->wIndex);
9834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
9854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
986598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		status = 1 << USB_DEVICE_SELF_POWERED;
9874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
9894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		status = 0;
9904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT:
992598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
9934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = control_reg_get_pid(m66592, ep->pipenum);
9944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (pid == M66592_PID_STALL)
995598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			status = 1 << USB_ENDPOINT_HALT;
9964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
9974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			status = 0;
9984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;		/* exit */
10024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1004598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_data = cpu_to_le16(status);
1005598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->buf = &m66592->ep0_data;
10064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req->length = 2;
100753b67950026ee642b43615f46df22ec3d36b4a53Al Viro	/* AV: what happens if we get called again before that gets through? */
1008598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
10094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
1010598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
10114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
10174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
10244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
1025598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1027598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, ep->pipenum);
10294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_reg_sqclr(m66592, ep->pipenum);
10304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next,
10344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request, queue);
10354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->busy) {
10364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->busy = 0;
10374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (list_empty(&ep->queue))
10384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				break;
10394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
10404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else if (!list_empty(&ep->queue))
10414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_start(m66592, ep->pipenum);
10424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1052ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda	u16 tmp;
1053ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda	int timeout = 3000;
10544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
1057ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		switch (le16_to_cpu(ctrl->wValue)) {
1058ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		case USB_DEVICE_TEST_MODE:
1059ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			control_end(m66592, 1);
1060ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			/* Wait for the completion of status stage */
1061ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			do {
1062ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda				tmp = m66592_read(m66592, M66592_INTSTS0) &
1063ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda								M66592_CTSQ;
1064ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda				udelay(1);
1065ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			} while (tmp != M66592_CS_IDST || timeout-- > 0);
1066ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda
1067ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			if (tmp == M66592_CS_IDST)
1068ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda				m66592_bset(m66592,
1069ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda					    le16_to_cpu(ctrl->wIndex >> 8),
1070ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda					    M66592_TESTMODE);
1071ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			break;
1072ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		default:
1073ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			pipe_stall(m66592, 0);
1074ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			break;
1075ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		}
10764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
1082598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1084598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, ep->pipenum);
10864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if return value is true, call class driver's setup() */
10974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 *p = (u16 *)ctrl;
11004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset = M66592_USBREQ;
11014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i, ret = 0;
11024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
11044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
11054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < 4; i++)
11074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		p[i] = m66592_read(m66592, offset + i*2);
11084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check request */
11104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
11114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		switch (ctrl->bRequest) {
11124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_GET_STATUS:
11134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			get_status(m66592, ctrl);
11144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_CLEAR_FEATURE:
11164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			clear_feature(m66592, ctrl);
11174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_SET_FEATURE:
11194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			set_feature(m66592, ctrl);
11204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		default:
11224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ret = 1;
11234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
11264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = 1;
11274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
11284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_update_usb_speed(struct m66592 *m66592)
11314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 speed = get_usb_speed(m66592);
11334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (speed) {
11354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_HSMODE:
11364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_HIGH;
11374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_FSMODE:
11394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_FULL;
11404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
11424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_UNKNOWN;
114300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("USB speed unknown\n");
11444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_device_state(struct m66592 *m66592)
11484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 dvsq;
11504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
11524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
11534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (dvsq == M66592_DS_DFLT) {	/* bus reset */
11554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->driver->disconnect(&m66592->gadget);
11564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
11594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
1160598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
1161598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			&& m66592->gadget.speed == USB_SPEED_UNKNOWN)
11624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->old_dvsq = dvsq;
11654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_control_stage(struct m66592 *m66592)
1168598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
1169598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
11704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct usb_ctrlrequest ctrl;
11724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
11734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
11754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
11764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
11784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_IDST: {
11794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
11804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
11814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
11824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
11834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
11844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
11884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
11894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
11904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (setup_packet(m66592, &ctrl)) {
1191598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_unlock(&m66592->lock);
11924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
11934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				pipe_stall(m66592, 0);
1194598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_lock(&m66592->lock);
11954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDSS:
11984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRSS:
11994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 0);
12004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
12014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
120200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
12034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
12044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic irqreturn_t m66592_irq(int irq, void *_m66592)
12084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = _m66592;
12104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intsts0;
12114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intenb0;
12124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdysts, nrdysts, bempsts;
12134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdyenb, nrdyenb, bempenb;
12144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 savepipe;
12154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 mask0;
12164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1217598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
1218598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
12194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intsts0 = m66592_read(m66592, M66592_INTSTS0);
12204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intenb0 = m66592_read(m66592, M66592_INTENB0);
12214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
12238c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		/*
12248c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * When USB clock stops, it cannot read register. Even if a
12258c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * clock stops, the interrupt occurs. So this driver turn on
12268c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * a clock by this timing and do re-reading of register.
12278c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 */
12288c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		m66592_start_xclock(m66592);
12298c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intsts0 = m66592_read(m66592, M66592_INTSTS0);
12308c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intenb0 = m66592_read(m66592, M66592_INTENB0);
12318c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	}
12328c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
12334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
12344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	mask0 = intsts0 & intenb0;
12364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (mask0) {
12374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdysts = m66592_read(m66592, M66592_BRDYSTS);
12384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdysts = m66592_read(m66592, M66592_NRDYSTS);
12394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempsts = m66592_read(m66592, M66592_BEMPSTS);
12404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdyenb = m66592_read(m66592, M66592_BRDYENB);
12414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdyenb = m66592_read(m66592, M66592_NRDYENB);
12424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempenb = m66592_read(m66592, M66592_BEMPENB);
12434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (mask0 & M66592_VBINT) {
1245598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			m66592_write(m66592,  0xffff & ~M66592_VBINT,
1246598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					M66592_INTSTS0);
12474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_start_xclock(m66592);
12484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			/* start vbus sampling */
12504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
1251598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					& M66592_VBSTS;
12524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1255598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_DVSQ)
12584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_device_state(m66592);
12594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1260598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
1261598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (brdysts & brdyenb)) {
12624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_ready(m66592, brdysts, brdyenb);
12634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
1264598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
1265598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (bempsts & bempenb)) {
12664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_empty(m66592, bempsts, bempenb);
12674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_CTRT)
12704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_control_stage(m66592);
12714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, savepipe, M66592_CFIFOSEL);
12744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1275598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
12764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return IRQ_HANDLED;
12774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_timer(unsigned long _m66592)
12804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = (struct m66592 *)_m66592;
12824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
12834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
12844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
12864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_SYSCFG);
12874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!(tmp & M66592_RCKE)) {
12884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
12894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		udelay(10);
12904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
12914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->scount > 0) {
12934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
12944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (tmp == m66592->old_vbus) {
12954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount--;
12964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->scount == 0) {
12974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (tmp == M66592_VBSTS)
12984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_connect(m66592);
12994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
13004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_disconnect(m66592);
13014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
13024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				mod_timer(&m66592->timer,
1303598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
13044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
13054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
13064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
13074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = tmp;
13084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1309598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
13104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
13114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
13134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
13164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_enable(struct usb_ep *_ep,
13174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 const struct usb_endpoint_descriptor *desc)
13184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return alloc_pipe_config(ep, desc);
13234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_disable(struct usb_ep *_ep)
13264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(!ep);
13334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	while (!list_empty(&ep->queue)) {
13354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
13364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_lock_irqsave(&ep->m66592->lock, flags);
13374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
13384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_unlock_irqrestore(&ep->m66592->lock, flags);
13394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_irq_disable(ep->m66592, ep->pipenum);
13424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return free_pipe_config(ep);
13434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
13464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						gfp_t gfp_flags)
13474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = kzalloc(sizeof(struct m66592_request), gfp_flags);
13514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!req)
13524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return NULL;
13534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&req->queue);
13554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return &req->req;
13574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
13604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(req);
13654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
13684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags)
13694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int request = 0;
13744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
13794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ESHUTDOWN;
13804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue))
13844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		request = 1;
13854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_add_tail(&req->queue, &ep->queue);
13874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual = 0;
13884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.status = -EINPROGRESS;
13894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1390a9475226977917afd5a85621f8a3d7f380a9da31David Brownell	if (ep->desc == NULL)	/* control */
13914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0(ep, req);
13924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else {
13934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (request && !ep->busy)
13944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
13954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
13984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
14004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
14034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
14064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
14104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
14134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
14144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
14174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_set_halt(struct usb_ep *_ep, int value)
14204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
14234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
14254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = list_entry(ep->queue.next, struct m66592_request, queue);
14284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue)) {
14314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -EAGAIN;
14324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto out;
14334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (value) {
14354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 1;
14364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(ep->m66592, ep->pipenum);
14374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
14384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 0;
14394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaout:
14434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
14454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_fifo_flush(struct usb_ep *_ep)
14484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue) && !ep->busy) {
14554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
14574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_ep_ops m66592_ep_ops = {
14624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.enable		= m66592_enable,
14634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.disable	= m66592_disable,
14644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.alloc_request	= m66592_alloc_request,
14664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.free_request	= m66592_free_request,
14674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.queue		= m66592_queue,
14694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.dequeue	= m66592_dequeue,
14704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.set_halt	= m66592_set_halt,
14724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.fifo_flush	= m66592_fifo_flush,
14734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
14744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
14764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct m66592 *the_controller;
14774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14780f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorstatic int m66592_start(struct usb_gadget_driver *driver,
1479b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König		int (*bind)(struct usb_gadget *))
14804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
14824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int retval;
14834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1484598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (!driver
1485598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| driver->speed != USB_SPEED_HIGH
1486b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König			|| !bind
1487598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| !driver->setup)
14884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
14894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!m66592)
14904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENODEV;
14914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->driver)
14924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EBUSY;
14934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* hook up the driver */
14954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->driver.bus = NULL;
14964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = driver;
14974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = &driver->driver;
14984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	retval = device_add(&m66592->gadget.dev);
15004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
150100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("device_add error (%d)\n", retval);
15024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
15034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1505b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König	retval = bind(&m66592->gadget);
15064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
150700274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("bind to driver error (%d)\n", retval);
15084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		device_del(&m66592->gadget.dev);
15094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
15104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
15134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
15144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_start_xclock(m66592);
15154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		/* start vbus sampling */
15164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->old_vbus = m66592_read(m66592,
15174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					 M66592_INTSTS0) & M66592_VBSTS;
15184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->scount = M66592_MAX_SAMPLING;
1519598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
15204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaerror:
15254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = NULL;
15274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return retval;
15294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15310f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorstatic int m66592_stop(struct usb_gadget_driver *driver)
15324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
15344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
15354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1536598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (driver != m66592->driver || !driver->unbind)
1537598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		return -EINVAL;
1538598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
15404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
15414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_usb_disconnect(m66592);
15424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
15434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
15454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->unbind(&m66592->gadget);
1547eb0be47dbbdca133b1b94adc564297f25176b3abPatrik Sevallius	m66592->gadget.dev.driver = NULL;
15484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
15504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
15514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_del(&m66592->gadget.dev);
15534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
15584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_get_frame(struct usb_gadget *_gadget)
15594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = gadget_to_m66592(_gadget);
15614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
15624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15647eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimodastatic int m66592_pullup(struct usb_gadget *gadget, int is_on)
15657eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda{
15667eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	struct m66592 *m66592 = gadget_to_m66592(gadget);
15677eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	unsigned long flags;
15687eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda
15697eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
15707eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	if (is_on)
15717eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda		m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
15727eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	else
15737eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
15747eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
15757eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda
15767eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	return 0;
15777eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda}
15787eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda
15794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_gadget_ops m66592_gadget_ops = {
15804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.get_frame		= m66592_get_frame,
15810f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	.start			= m66592_start,
15820f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	.stop			= m66592_stop,
15837eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	.pullup			= m66592_pullup,
15844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
15854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1586598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic int __exit m66592_remove(struct platform_device *pdev)
15874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
15894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15900f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	usb_del_gadget_udc(&m66592->gadget);
15910f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
15924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	del_timer_sync(&m66592->timer);
15934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	iounmap(m66592->reg);
15944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	free_irq(platform_get_irq(pdev, 0), m66592);
1595598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
15962c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
15972c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
15982c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_disable(m66592->clk);
15992c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_put(m66592->clk);
16002c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
1601af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
16024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(m66592);
16034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
16044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
16054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1606598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic void nop_completion(struct usb_ep *ep, struct usb_request *r)
1607598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda{
1608598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda}
1609598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
16104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_probe(struct platform_device *pdev)
16114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
16122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	struct resource *res, *ires;
16134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void __iomem *reg = NULL;
16144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = NULL;
16152c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
1616af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm	char clk_name[8];
1617af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
16184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
16194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
16204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16210a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
16224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!res) {
16234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
16240a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm		pr_err("platform_get_resource error.\n");
16254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16282c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
16292c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!ires) {
16304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
16312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		dev_err(&pdev->dev,
16322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			"platform_get_resource IORESOURCE_IRQ error.\n");
16334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16360a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm	reg = ioremap(res->start, resource_size(res));
16374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg == NULL) {
16384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENOMEM;
163900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ioremap error.\n");
16404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16432c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (pdev->dev.platform_data == NULL) {
16442c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		dev_err(&pdev->dev, "no platform data\n");
16452c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		ret = -ENODEV;
16462c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		goto clean_up;
16472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
16482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
16494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* initialize ucd */
16504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
16514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592 == NULL) {
16527c81aafaf059b81ead2330bc13db78269ef62612Julia Lawall		ret = -ENOMEM;
165300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("kzalloc error\n");
16544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16572c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592->pdata = pdev->dev.platform_data;
16582c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
16592c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
16604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_init(&m66592->lock);
16614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dev_set_drvdata(&pdev->dev, m66592);
16624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ops = &m66592_gadget_ops;
16644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_initialize(&m66592->gadget.dev);
1665836e4b14b41d19d17341a2dd2c49af8dd54e3aacPaul Mundt	dev_set_name(&m66592->gadget.dev, "gadget");
16664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.is_dualspeed = 1;
16674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.parent = &pdev->dev;
16684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
16694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.release = pdev->dev.release;
16704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.name = udc_name;
16714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_timer(&m66592->timer);
16734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.function = m66592_timer;
16744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.data = (unsigned long)m66592;
16754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->reg = reg;
16764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16772c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	ret = request_irq(ires->start, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
1678598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			udc_name, m66592);
16794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
168000274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("request_irq error (%d)\n", ret);
16814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16842c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
16852c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
16862c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
16872c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592->clk = clk_get(&pdev->dev, clk_name);
16882c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (IS_ERR(m66592->clk)) {
16892c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
16902c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm				clk_name);
16912c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			ret = PTR_ERR(m66592->clk);
16922c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			goto clean_up2;
16932c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
16942c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_enable(m66592->clk);
1695af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm	}
1696af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
16974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep_list);
16984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ep0 = &m66592->ep[0].ep;
16994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
17004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
17014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep = &m66592->ep[i];
17024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i != 0) {
17044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
17054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			list_add_tail(&m66592->ep[i].ep.ep_list,
1706598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&m66592->gadget.ep_list);
17074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
17084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->m66592 = m66592;
17094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		INIT_LIST_HEAD(&ep->queue);
17104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.name = m66592_ep_name[i];
17114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.ops = &m66592_ep_ops;
17124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.maxpacket = 512;
17134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
17144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].ep.maxpacket = 64;
17154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipenum = 0;
17164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoaddr = M66592_CFIFO;
17174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifosel = M66592_CFIFOSEL;
17184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoctr = M66592_CFIFOCTR;
17194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifotrn = 0;
17204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipectr = get_pipectr_addr(0);
17214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[0] = &m66592->ep[0];
17224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[0] = &m66592->ep[0];
17234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	the_controller = m66592;
17254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
17274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->ep0_req == NULL)
1728af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm		goto clean_up3;
1729598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->complete = nop_completion;
17304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
17324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17330f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
17340f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	if (ret)
17350f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior		goto err_add_udc;
17360f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
1737598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
17384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
17394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17400f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorerr_add_udc:
17410f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
17420f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
1743af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Dammclean_up3:
17442c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
17452c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
17462c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_disable(m66592->clk);
17472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_put(m66592->clk);
17482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
1749598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodaclean_up2:
1750d6435102d4ca3b5655c0105abe924abec17ffeb8Paul Mundt#endif
17512c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	free_irq(ires->start, m66592);
17524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaclean_up:
17534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592) {
17544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->ep0_req)
17554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
17564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		kfree(m66592);
17574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
17584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg)
17594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		iounmap(reg);
17604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
17624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
17654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct platform_driver m66592_driver = {
1766598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	.remove =	__exit_p(m66592_remove),
17674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.driver		= {
17684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		.name =	(char *) udc_name,
1769f34c32f13ce8c539f3f582562358e39a86b00e83Kay Sievers		.owner	= THIS_MODULE,
17704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	},
17714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
17724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_udc_init(void)
17744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1775598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	return platform_driver_probe(&m66592_driver, m66592_probe);
17764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_init(m66592_udc_init);
17784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void __exit m66592_udc_cleanup(void)
17804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
17814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	platform_driver_unregister(&m66592_driver);
17824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_exit(m66592_udc_cleanup);
1784