m66592-udc.c revision f34c32f13ce8c539f3f582562358e39a86b00e83
14cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*
24cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * M66592 UDC (USB gadget)
34cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
44cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * Copyright (C) 2006-2007 Renesas Solutions Corp.
54cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
64cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * Author : Yoshihiro Shimoda <shimoda.yoshihiro@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>
28598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/usb/ch9.h>
309454a57ab5922e5cd25321cae9d1a8cbeb3e2e85David Brownell#include <linux/usb/gadget.h>
314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include "m66592-udc.h"
334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
34598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro 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
408c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#define DRIVER_VERSION	"18 Oct 2007"
414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* module parameters */
438c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
448c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimodastatic unsigned short endian = M66592_LITTLE;
458c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimodamodule_param(endian, ushort, 0644);
468c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro ShimodaMODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
478c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#else
484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic unsigned short clock = M66592_XTAL24;
494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_param(clock, ushort, 0644);
50598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
51598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		"(default=16384)");
52598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic unsigned short vif = M66592_LDRV;
544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_param(vif, ushort, 0644);
55598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)");
56598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
57598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic unsigned short endian;
584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_param(endian, ushort, 0644);
59598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)");
60598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic unsigned short irq_sense = M66592_INTL;
624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_param(irq_sense, ushort, 0644);
63598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
64598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		"(default=2)");
658c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#endif
664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char udc_name[] = "m66592_udc";
684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char *m66592_ep_name[] = {
694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	"ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592);
734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags);
774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
79598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status);
80598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 get_usb_speed(struct m66592 *m66592)
834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
88598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
94598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, (1 << pipenum), reg);
964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
100598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
1014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
1034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
1054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
106598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
1074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, (1 << pipenum), reg);
1084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
1094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_connect(struct m66592 *m66592)
1124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
1144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
115598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
1164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
1174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
1194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_disconnect(struct m66592 *m66592)
122598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
123598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
1244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
1264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
127598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
1284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
1294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
1304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.speed = USB_SPEED_UNKNOWN;
1324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock(&m66592->lock);
1334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver->disconnect(&m66592->gadget);
1344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock(&m66592->lock);
1354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
1374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->ep[0].queue);
1384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
1414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid = 0;
1434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
1474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, offset) & M66592_PID;
1504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
15100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return pid;
1544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
157598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pid)
1584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
1634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, offset);
1664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
16700274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_start(struct m66592 *m66592, u16 pipenum)
1714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
1734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
1764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
1784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
1814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
1834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
1864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ret = 0;
1884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, M66592_DCPCTR);
1924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, offset);
1954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
19600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
1994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
2024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
2044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_stop(m66592, pipenum);
2064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
2084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
2094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
2104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
2114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, offset);
2124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
21300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num(%d)\n", pipenum);
2144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
2174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
2194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
2204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0) {
2224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_DCPCFG);
2234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0)
2244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = 256;
2254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else {
2264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_DCPMAXP);
2274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MAXP;
2284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
2304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, pipenum, M66592_PIPESEL);
2314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_PIPECFG);
2324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0) {
2334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEBUF);
2344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = ((tmp >> 10) + 1) * 64;
2354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
2364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEMAXP);
2374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MXPS;
2384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return size;
2424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_change(struct m66592 *m66592, u16 pipenum)
2454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
2474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
2494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
2524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ndelay(450);
2544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_MBW, ep->fifosel);
2564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int pipe_buffer_setting(struct m66592 *m66592,
259598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_pipe_info *info)
2604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 bufnum = 0, buf_bsize = 0;
2624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipecfg = 0;
2634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
2664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->pipe, M66592_PIPESEL);
2684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->dir_in)
2704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DIR;
2714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->type;
2724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->epnum;
2734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (info->type) {
2744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_INT:
2754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
2764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 0;
2774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_BULK:
2794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bufnum = m66592->bi_bufnum +
2804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 (info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
2814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bi_bufnum += 16;
2824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DBLB;
2844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (!info->dir_in)
2854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipecfg |= M66592_SHTNAK;
2864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_ISO:
2884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bufnum = m66592->bi_bufnum +
2894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
2904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bi_bufnum += 16;
2914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
29500274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("m66592 pipe memory is insufficient(%d)\n",
296598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				m66592->bi_bufnum);
2974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENOMEM;
2984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, pipecfg, M66592_PIPECFG);
3014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
3024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
3034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->interval)
3044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info->interval--;
3054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->interval, M66592_PIPEPERI);
3064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
3084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_buffer_release(struct m66592 *m66592,
3114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				struct m66592_pipe_info *info)
3124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
3144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
3154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (info->type) {
3174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_BULK:
3184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (is_bulk_pipe(info->pipe))
3194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->bi_bufnum -= 16;
3204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
3214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_ISO:
3224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (is_isoc_pipe(info->pipe))
3234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->bi_bufnum -= 16;
3244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
3254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (is_bulk_pipe(info->pipe)) {
3284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk--;
3294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else if (is_interrupt_pipe(info->pipe))
3304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->interrupt--;
3314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (is_isoc_pipe(info->pipe)) {
3324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->isochronous--;
3334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (info->type == M66592_BULK)
3344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->bulk--;
3354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
33600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ep_release: unexpect pipenum (%d)\n",
337598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info->pipe);
3384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_initialize(struct m66592_ep *ep)
3414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
3454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_ACLRM, ep->pipectr);
3474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, 0, ep->pipectr);
3484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_SQCLR, ep->pipectr);
3494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma) {
3504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
3514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(450);
3534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_MBW, ep->fifosel);
3554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
359598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc,
360598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pipenum, int dma)
3614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((pipenum != 0) && dma) {
3634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->num_dma == 0) {
3644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D0FIFO;
3674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D0FIFOSEL;
3684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D0FIFOCTR;
3694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D0FIFOTRN;
3708c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
3714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else if (m66592->num_dma == 1) {
3724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D1FIFO;
3754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D1FIFOSEL;
3764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D1FIFOCTR;
3774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D1FIFOTRN;
3788c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#endif
3794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
3804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 0;
3814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_CFIFO;
3824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_CFIFOSEL;
3834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_CFIFOCTR;
3844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = 0;
3854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
3864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
3874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->use_dma = 0;
3884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoaddr = M66592_CFIFO;
3894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifosel = M66592_CFIFOSEL;
3904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoctr = M66592_CFIFOCTR;
3914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifotrn = 0;
3924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipectr = get_pipectr_addr(pipenum);
3954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = pipenum;
396598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
3974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[pipenum] = ep;
3984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
3994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&ep->queue);
4004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_release(struct m66592_ep *ep)
4034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
4054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
4064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
4084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
4094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
4114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->num_dma--;
4124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = 0;
4134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->busy = 0;
4144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->use_dma = 0;
4154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int alloc_pipe_config(struct m66592_ep *ep,
418598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc)
4194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
4214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
4224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int dma = 0;
4234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int *counter;
4244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret;
4254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->desc = desc;
4274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(ep->pipenum);
4294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
430598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
4314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_BULK:
4324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
4334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
43400274921a052d3232d9f00856387fb269ac0af11David Brownell				pr_err("bulk pipe is insufficient\n");
4354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				return -ENODEV;
4364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
437598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info.pipe = M66592_BASE_PIPENUM_ISOC
438598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda						+ m66592->isochronous;
4394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				counter = &m66592->isochronous;
4404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
4414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
4424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
4434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			counter = &m66592->bulk;
4444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_BULK;
4464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		dma = 1;
4474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_INT:
4494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
45000274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("interrupt pipe is insufficient\n");
4514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
4544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_INT;
4554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->interrupt;
4564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_ISOC:
4584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
45900274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("isochronous pipe is insufficient\n");
4604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
4634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_ISO;
4644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->isochronous;
4654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
46700274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect xfer type\n");
4684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
4694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->type = info.type;
4714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
473598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
4744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.interval = desc->bInterval;
4754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
4764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 1;
4774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
4784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 0;
4794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ret = pipe_buffer_setting(m66592, &info);
4814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
48200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("pipe_buffer_setting fail\n");
4834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return ret;
4844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	(*counter)++;
4874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
4884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk++;
4894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
4914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_initialize(ep);
4924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int free_pipe_config(struct m66592_ep *ep)
4974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
4994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
5004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.pipe = ep->pipenum;
5024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.type = ep->type;
5034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_buffer_release(m66592, &info);
5044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_release(ep);
5054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
5074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
5104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
5114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_ready(m66592, pipenum);
5134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_nrdy(m66592, pipenum);
5144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
5174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_ready(m66592, pipenum);
5194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_nrdy(m66592, pipenum);
5204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if complete is true, gadget driver complete function is not call */
5234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void control_end(struct m66592 *m66592, unsigned ccpl)
5244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].internal_ccpl = ccpl;
5264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, 0);
5274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
5284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
5314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
536598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			(M66592_ISEL | M66592_CURPIPE),
537598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_CFIFOSEL);
5384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.length == 0) {
5404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
5414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, 0);
5424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
5434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
5454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
5464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
5504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
5534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_empty(m66592, ep->pipenum);
5564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, ep->pipenum);
5574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
5594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0))
5604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, ep->pipenum);
5614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_write(ep, req);
5634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
5664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
5694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->pipenum == 0) {
5714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0,
572598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(M66592_ISEL | M66592_CURPIPE),
573598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
5744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);
5764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->use_dma) {
5794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
5804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_change(m66592, pipenum);
5814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRENB, ep->fifosel);
5824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592,
583598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(req->req.length + ep->ep.maxpacket - 1)
584598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					/ ep->ep.maxpacket,
585598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				ep->fifotrn);
5864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
5874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);	/* trigger once */
5884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet(struct m66592_ep *ep, struct m66592_request *req)
5934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->desc->bEndpointAddress & USB_DIR_IN)
5954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_write(ep, req);
5964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
6014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
6024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
6034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
6054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
6074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
6084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0_write(ep, req);
6094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
6104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
6114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
6124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
6134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
6154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(ep->m66592, 0);
6164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
6174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
61800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
6194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
6204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
6214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6238c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
6248c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimodastatic void init_controller(struct m66592 *m66592)
6258c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda{
6268c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	usbf_start_clock();
6278c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
6288c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6298c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6308c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6318c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6328c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	/* This is a workaound for SH7722 2nd cut */
6338c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
6348c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, 0x1000, M66592_TESTMODE);
6358c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
6368c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6378c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
6388c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6398c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_write(m66592, 0, M66592_CFBCFG);
6408c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_write(m66592, 0, M66592_D0FBCFG);
6418c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, endian, M66592_CFBCFG);
6428c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	m66592_bset(m66592, endian, M66592_D0FBCFG);
6438c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda}
6448c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#else	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
6454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void init_controller(struct m66592 *m66592)
6464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
6474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
648598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_PINCFG);
6494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
6504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
6514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
6574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	msleep(3);
6594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
6614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	msleep(1);
6634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
6654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
6674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
668598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_DMA0CFG);
6694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6708c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
6714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592)
6734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
6748c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
6758c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	usbf_stop_clock();
6768c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#else
6774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
6784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	udelay(1);
6794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
6804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	udelay(1);
6814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
6824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	udelay(1);
6834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
6848c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#endif
6854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_start_xclock(struct m66592 *m66592)
6884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
6898c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
6908c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	usbf_start_clock();
6918c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#else
6924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
6934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_SYSCFG);
6954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!(tmp & M66592_XCKE))
6964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
6978c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#endif
6984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
7014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
702598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status)
703598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
704598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
7054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int restart = 0;
7074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely(ep->pipenum == 0)) {
7094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->internal_ccpl) {
7104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->internal_ccpl = 0;
7114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_del_init(&req->queue);
7164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
7174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -ESHUTDOWN;
7184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
7194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = status;
7204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
7224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		restart = 1;
7234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
724598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&ep->m66592->lock);
725598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	req->req.complete(&ep->ep, &req->req);
726598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&ep->m66592->lock);
7274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (restart) {
7294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
7304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->desc)
7314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
7324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
7364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
738598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 tmp;
7394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
7404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
7414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
7424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
7434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
7444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
7464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_ISEL, ep->fifosel);
7474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	i = 0;
7494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	do {
7504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, ep->fifoctr);
7514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i++ > 100000) {
75200274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("pipe0 is busy. maybe cpu i/o bus "
7534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				"conflict. please power off this controller.");
7544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(1);
7574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} while ((tmp & M66592_FRDY) == 0);
7584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
7604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
7614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
7624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
7634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
7654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
7664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size > 0)
7674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
7684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
7694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
7704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
7734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
7744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
776598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
777598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
778598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
7794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
7814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
7824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
7844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, pipenum);
7864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
7894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
7914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
7924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
7934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
7944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
7954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
7964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
7984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
7994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
80200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("write fifo not ready. pipnum=%d\n", pipenum);
8034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
8104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
8124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
8134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
814598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((size == 0)
815598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((size % ep->ep.maxpacket) != 0)
816598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((bufsize != ep->ep.maxpacket)
817598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&& (bufsize > size)))
8184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
8194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
824598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
825598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
826598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
8284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
8294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
8304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
8314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
8324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
8364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
8384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int rcv_len, bufsize, req_len;
8394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
8404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int finish = 0;
8444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -EPIPE;
8494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
85100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("read fifo not ready");
8524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	rcv_len = tmp & M66592_DTLN;
8574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req_len = req->req.length - req->req.actual;
8614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (rcv_len < bufsize)
8624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(rcv_len, req_len);
8634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
8644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(bufsize, req_len);
8654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
870598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
871598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
872598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
8754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		finish = 1;
8764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
8794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
8804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size == 0)
8814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592, M66592_BCLR, ep->fifoctr);
8824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
8834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
8844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ep->pipenum != 0) && finish)
8874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
8884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
8914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
8934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
8944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
8954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
8964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
8984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
8994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
900598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
9014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_read(ep, req);
9054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BRDYSTS);
9104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				ep = m66592->pipenum2ep[pipenum];
9114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				req = list_entry(ep->queue.next,
9124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						 struct m66592_request, queue);
9134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (ep->desc->bEndpointAddress & USB_DIR_IN)
9144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_write(ep, req);
9154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
9164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_read(ep, req);
9174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
9234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
9254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
9314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
9324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
9364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BEMPSTS);
9414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				tmp = control_reg_get(m66592, pipenum);
9424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if ((tmp & M66592_INBUFM) == 0) {
9434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					disable_irq_empty(m66592, pipenum);
9444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_irq_disable(m66592, pipenum);
9454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_stop(m66592, pipenum);
9464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					ep = m66592->pipenum2ep[pipenum];
9474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					req = list_entry(ep->queue.next,
9484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 struct m66592_request,
9494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 queue);
9504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					if (!list_empty(&ep->queue))
9514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						transfer_complete(ep, req, 0);
9524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				}
9534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
959598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
960598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
9614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid;
9644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 status = 0;
965598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 w_index = le16_to_cpu(ctrl->wIndex);
9664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
9684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
969598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		status = 1 << USB_DEVICE_SELF_POWERED;
9704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
9724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		status = 0;
9734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT:
975598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
9764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = control_reg_get_pid(m66592, ep->pipenum);
9774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (pid == M66592_PID_STALL)
978598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			status = 1 << USB_ENDPOINT_HALT;
9794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
9804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			status = 0;
9814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
9834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
9844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;		/* exit */
9854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
987598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_data = cpu_to_le16(status);
988598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->buf = &m66592->ep0_data;
9894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req->length = 2;
99053b67950026ee642b43615f46df22ec3d36b4a53Al Viro	/* AV: what happens if we get called again before that gets through? */
991598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
9924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
993598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
9944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
9974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
9994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
10004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
10074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
1008598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1010598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, ep->pipenum);
10124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_reg_sqclr(m66592, ep->pipenum);
10134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next,
10174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request, queue);
10184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->busy) {
10194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->busy = 0;
10204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (list_empty(&ep->queue))
10214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				break;
10224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
10234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else if (!list_empty(&ep->queue))
10244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_start(m66592, ep->pipenum);
10254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
10384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
1045598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1047598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, ep->pipenum);
10494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if return value is true, call class driver's setup() */
10604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 *p = (u16 *)ctrl;
10634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset = M66592_USBREQ;
10644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i, ret = 0;
10654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
10674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
10684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < 4; i++)
10704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		p[i] = m66592_read(m66592, offset + i*2);
10714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check request */
10734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
10744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		switch (ctrl->bRequest) {
10754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_GET_STATUS:
10764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			get_status(m66592, ctrl);
10774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
10784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_CLEAR_FEATURE:
10794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			clear_feature(m66592, ctrl);
10804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
10814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_SET_FEATURE:
10824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			set_feature(m66592, ctrl);
10834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
10844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		default:
10854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ret = 1;
10864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
10874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
10894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = 1;
10904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
10914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_update_usb_speed(struct m66592 *m66592)
10944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 speed = get_usb_speed(m66592);
10964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (speed) {
10984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_HSMODE:
10994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_HIGH;
11004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_FSMODE:
11024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_FULL;
11034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
11054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_UNKNOWN;
110600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("USB speed unknown\n");
11074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_device_state(struct m66592 *m66592)
11114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 dvsq;
11134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
11154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
11164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (dvsq == M66592_DS_DFLT) {	/* bus reset */
11184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->driver->disconnect(&m66592->gadget);
11194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
11224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
1123598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
1124598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			&& m66592->gadget.speed == USB_SPEED_UNKNOWN)
11254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->old_dvsq = dvsq;
11284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_control_stage(struct m66592 *m66592)
1131598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
1132598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
11334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct usb_ctrlrequest ctrl;
11354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
11364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
11384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
11394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
11414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_IDST: {
11424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
11434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
11444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
11454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
11464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
11474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
11514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
11524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
11534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (setup_packet(m66592, &ctrl)) {
1154598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_unlock(&m66592->lock);
11554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
11564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				pipe_stall(m66592, 0);
1157598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_lock(&m66592->lock);
11584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDSS:
11614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRSS:
11624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 0);
11634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
116500274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
11664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic irqreturn_t m66592_irq(int irq, void *_m66592)
11714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = _m66592;
11734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intsts0;
11744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intenb0;
11754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdysts, nrdysts, bempsts;
11764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdyenb, nrdyenb, bempenb;
11774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 savepipe;
11784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 mask0;
11794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1180598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
1181598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
11824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intsts0 = m66592_read(m66592, M66592_INTSTS0);
11834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intenb0 = m66592_read(m66592, M66592_INTENB0);
11844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11858c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
11868c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	if (!intsts0 && !intenb0) {
11878c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		/*
11888c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * When USB clock stops, it cannot read register. Even if a
11898c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * clock stops, the interrupt occurs. So this driver turn on
11908c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * a clock by this timing and do re-reading of register.
11918c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 */
11928c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		m66592_start_xclock(m66592);
11938c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intsts0 = m66592_read(m66592, M66592_INTSTS0);
11948c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intenb0 = m66592_read(m66592, M66592_INTENB0);
11958c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	}
11968c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda#endif
11978c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
11984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
11994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	mask0 = intsts0 & intenb0;
12014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (mask0) {
12024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdysts = m66592_read(m66592, M66592_BRDYSTS);
12034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdysts = m66592_read(m66592, M66592_NRDYSTS);
12044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempsts = m66592_read(m66592, M66592_BEMPSTS);
12054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdyenb = m66592_read(m66592, M66592_BRDYENB);
12064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdyenb = m66592_read(m66592, M66592_NRDYENB);
12074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempenb = m66592_read(m66592, M66592_BEMPENB);
12084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (mask0 & M66592_VBINT) {
1210598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			m66592_write(m66592,  0xffff & ~M66592_VBINT,
1211598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					M66592_INTSTS0);
12124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_start_xclock(m66592);
12134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			/* start vbus sampling */
12154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
1216598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					& M66592_VBSTS;
12174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1220598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_DVSQ)
12234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_device_state(m66592);
12244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1225598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
1226598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (brdysts & brdyenb)) {
12274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_ready(m66592, brdysts, brdyenb);
12284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
1229598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
1230598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (bempsts & bempenb)) {
12314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_empty(m66592, bempsts, bempenb);
12324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_CTRT)
12354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_control_stage(m66592);
12364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, savepipe, M66592_CFIFOSEL);
12394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1240598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
12414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return IRQ_HANDLED;
12424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_timer(unsigned long _m66592)
12454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = (struct m66592 *)_m66592;
12474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
12484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
12494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
12514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_SYSCFG);
12524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!(tmp & M66592_RCKE)) {
12534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
12544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		udelay(10);
12554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
12564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->scount > 0) {
12584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
12594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (tmp == m66592->old_vbus) {
12604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount--;
12614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->scount == 0) {
12624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (tmp == M66592_VBSTS)
12634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_connect(m66592);
12644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
12654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_disconnect(m66592);
12664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
12674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				mod_timer(&m66592->timer,
1268598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
12704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
12714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = tmp;
12734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1274598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
12784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
12814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_enable(struct usb_ep *_ep,
12824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 const struct usb_endpoint_descriptor *desc)
12834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
12854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
12874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return alloc_pipe_config(ep, desc);
12884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_disable(struct usb_ep *_ep)
12914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
12934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
12944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
12954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
12974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(!ep);
12984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	while (!list_empty(&ep->queue)) {
13004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
13014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_lock_irqsave(&ep->m66592->lock, flags);
13024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
13034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_unlock_irqrestore(&ep->m66592->lock, flags);
13044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_irq_disable(ep->m66592, ep->pipenum);
13074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return free_pipe_config(ep);
13084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
13114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						gfp_t gfp_flags)
13124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = kzalloc(sizeof(struct m66592_request), gfp_flags);
13164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!req)
13174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return NULL;
13184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&req->queue);
13204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return &req->req;
13224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
13254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(req);
13304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
13334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags)
13344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int request = 0;
13394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
13444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ESHUTDOWN;
13454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue))
13494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		request = 1;
13504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_add_tail(&req->queue, &ep->queue);
13524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual = 0;
13534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.status = -EINPROGRESS;
13544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1355a9475226977917afd5a85621f8a3d7f380a9da31David Brownell	if (ep->desc == NULL)	/* control */
13564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0(ep, req);
13574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else {
13584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (request && !ep->busy)
13594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
13604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
13634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
13654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
13684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
13784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
13794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
13804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
13824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_set_halt(struct usb_ep *_ep, int value)
13854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
13904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = list_entry(ep->queue.next, struct m66592_request, queue);
13934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue)) {
13964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -EAGAIN;
13974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto out;
13984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (value) {
14004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 1;
14014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(ep->m66592, ep->pipenum);
14024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
14034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 0;
14044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaout:
14084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
14104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_fifo_flush(struct usb_ep *_ep)
14134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue) && !ep->busy) {
14204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
14224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_ep_ops m66592_ep_ops = {
14274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.enable		= m66592_enable,
14284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.disable	= m66592_disable,
14294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.alloc_request	= m66592_alloc_request,
14314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.free_request	= m66592_free_request,
14324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.queue		= m66592_queue,
14344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.dequeue	= m66592_dequeue,
14354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.set_halt	= m66592_set_halt,
14374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.fifo_flush	= m66592_fifo_flush,
14384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
14394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
14414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct m66592 *the_controller;
14424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaint usb_gadget_register_driver(struct usb_gadget_driver *driver)
14444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
14464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int retval;
14474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1448598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (!driver
1449598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| driver->speed != USB_SPEED_HIGH
1450598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| !driver->bind
1451598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| !driver->setup)
14524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
14534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!m66592)
14544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENODEV;
14554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->driver)
14564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EBUSY;
14574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* hook up the driver */
14594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->driver.bus = NULL;
14604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = driver;
14614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = &driver->driver;
14624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	retval = device_add(&m66592->gadget.dev);
14644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
146500274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("device_add error (%d)\n", retval);
14664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
14674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	retval = driver->bind (&m66592->gadget);
14704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
147100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("bind to driver error (%d)\n", retval);
14724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		device_del(&m66592->gadget.dev);
14734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
14744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
14774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
14784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_start_xclock(m66592);
14794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		/* start vbus sampling */
14804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->old_vbus = m66592_read(m66592,
14814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					 M66592_INTSTS0) & M66592_VBSTS;
14824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->scount = M66592_MAX_SAMPLING;
1483598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
14844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
14874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaerror:
14894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
14904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = NULL;
14914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return retval;
14934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaEXPORT_SYMBOL(usb_gadget_register_driver);
14954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaint usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
14974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
14994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
15004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1501598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (driver != m66592->driver || !driver->unbind)
1502598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		return -EINVAL;
1503598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
15054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
15064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_usb_disconnect(m66592);
15074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
15084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
15104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->unbind(&m66592->gadget);
1512eb0be47dbbdca133b1b94adc564297f25176b3abPatrik Sevallius	m66592->gadget.dev.driver = NULL;
15134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
15154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
15164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_del(&m66592->gadget.dev);
15184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaEXPORT_SYMBOL(usb_gadget_unregister_driver);
15224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
15244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_get_frame(struct usb_gadget *_gadget)
15254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = gadget_to_m66592(_gadget);
15274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
15284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_gadget_ops m66592_gadget_ops = {
15314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.get_frame		= m66592_get_frame,
15324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
15334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1534598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic int __exit m66592_remove(struct platform_device *pdev)
15354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
15374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	del_timer_sync(&m66592->timer);
15394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	iounmap(m66592->reg);
15404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	free_irq(platform_get_irq(pdev, 0), m66592);
1541598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
15428c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	usbf_stop_clock();
15434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(m66592);
15444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1547598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic void nop_completion(struct usb_ep *ep, struct usb_request *r)
1548598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda{
1549598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda}
1550598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#define resource_len(r) (((r)->end - (r)->start) + 1)
1552598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_probe(struct platform_device *pdev)
15544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1555598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	struct resource *res;
1556598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	int irq;
15574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void __iomem *reg = NULL;
15584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = NULL;
15594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
15604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
15614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1563598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			(char *)udc_name);
15644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!res) {
15654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
156600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("platform_get_resource_byname error.\n");
15674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
15684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	irq = platform_get_irq(pdev, 0);
15714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (irq < 0) {
15724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
157300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("platform_get_irq error.\n");
15744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
15754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	reg = ioremap(res->start, resource_len(res));
15784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg == NULL) {
15794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENOMEM;
158000274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ioremap error.\n");
15814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
15824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* initialize ucd */
15854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
15864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592 == NULL) {
158700274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("kzalloc error\n");
15884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
15894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_init(&m66592->lock);
15924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dev_set_drvdata(&pdev->dev, m66592);
15934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ops = &m66592_gadget_ops;
15954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_initialize(&m66592->gadget.dev);
15964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	strcpy(m66592->gadget.dev.bus_id, "gadget");
15974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.is_dualspeed = 1;
15984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.parent = &pdev->dev;
15994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
16004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.release = pdev->dev.release;
16014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.name = udc_name;
16024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_timer(&m66592->timer);
16044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.function = m66592_timer;
16054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.data = (unsigned long)m66592;
16064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->reg = reg;
16074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->bi_bufnum = M66592_BASE_BUFNUM;
16094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
161015a1d5c9271219db2f1bc448247fb8ccbcc08418Yoshihiro Shimoda	ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
1611598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			udc_name, m66592);
16124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
161300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("request_irq error (%d)\n", ret);
16144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep_list);
16184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ep0 = &m66592->ep[0].ep;
16194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
16204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
16214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep = &m66592->ep[i];
16224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i != 0) {
16244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
16254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			list_add_tail(&m66592->ep[i].ep.ep_list,
1626598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&m66592->gadget.ep_list);
16274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
16284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->m66592 = m66592;
16294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		INIT_LIST_HEAD(&ep->queue);
16304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.name = m66592_ep_name[i];
16314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.ops = &m66592_ep_ops;
16324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.maxpacket = 512;
16334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].ep.maxpacket = 64;
16354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipenum = 0;
16364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoaddr = M66592_CFIFO;
16374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifosel = M66592_CFIFOSEL;
16384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoctr = M66592_CFIFOCTR;
16394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifotrn = 0;
16404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipectr = get_pipectr_addr(0);
16414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[0] = &m66592->ep[0];
16424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[0] = &m66592->ep[0];
16434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	the_controller = m66592;
16454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
16474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->ep0_req == NULL)
1648598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		goto clean_up2;
1649598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->complete = nop_completion;
16504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
16524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1653598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
16544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
16554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1656598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodaclean_up2:
1657598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	free_irq(irq, m66592);
16584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaclean_up:
16594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592) {
16604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->ep0_req)
16614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
16624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		kfree(m66592);
16634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg)
16654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		iounmap(reg);
16664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
16684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
16694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
16714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct platform_driver m66592_driver = {
1672598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	.remove =	__exit_p(m66592_remove),
16734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.driver		= {
16744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		.name =	(char *) udc_name,
1675f34c32f13ce8c539f3f582562358e39a86b00e83Kay Sievers		.owner	= THIS_MODULE,
16764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	},
16774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
16784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_udc_init(void)
16804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1681598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	return platform_driver_probe(&m66592_driver, m66592_probe);
16824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
16834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_init(m66592_udc_init);
16844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void __exit m66592_udc_cleanup(void)
16864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
16874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	platform_driver_unregister(&m66592_driver);
16884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
16894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_exit(m66592_udc_cleanup);
1690