m66592-udc.c revision 0f91349b89f37dfad7b77f7829a105b6a0f526ec
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>
285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
2956fd1260a8de3738034588c6e32262960c5b2660Paul Mundt#include <linux/err.h>
304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/usb/ch9.h>
319454a57ab5922e5cd25321cae9d1a8cbeb3e2e85David Brownell#include <linux/usb/gadget.h>
324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include "m66592-udc.h"
344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
35598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_DESCRIPTION("M66592 USB gadget driver");
364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaMODULE_LICENSE("GPL");
374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaMODULE_AUTHOR("Yoshihiro Shimoda");
38f34c32f13ce8c539f3f582562358e39a86b00e83Kay SieversMODULE_ALIAS("platform:m66592_udc");
394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
402c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#define DRIVER_VERSION	"21 July 2009"
414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char udc_name[] = "m66592_udc";
434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char *m66592_ep_name[] = {
444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	"ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592);
484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags);
524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
54598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status);
55598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 get_usb_speed(struct m66592 *m66592)
584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
63598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
69598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, (1 << pipenum), reg);
714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
75598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
81598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, (1 << pipenum), reg);
834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_connect(struct m66592 *m66592)
874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
90598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_disconnect(struct m66592 *m66592)
97598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
98598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
1014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
102598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
1034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
1044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
1054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.speed = USB_SPEED_UNKNOWN;
1074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock(&m66592->lock);
1084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver->disconnect(&m66592->gadget);
1094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock(&m66592->lock);
1104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
1124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->ep[0].queue);
1134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
1164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid = 0;
1184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
1224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, offset) & M66592_PID;
1254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
12600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return pid;
1294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
132598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pid)
1334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
1384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, offset);
1414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
14200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_start(struct m66592 *m66592, u16 pipenum)
1464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
1484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
1514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
1534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
1564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
1584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
1614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ret = 0;
1634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, M66592_DCPCTR);
1674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, offset);
1704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
17100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
1744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
1774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_stop(m66592, pipenum);
1814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
1844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, offset);
1874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
18800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num(%d)\n", pipenum);
1894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
1924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
1944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
1954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0) {
1974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_DCPCFG);
1984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0)
1994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = 256;
2004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else {
2014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_DCPMAXP);
2024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MAXP;
2034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
2054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, pipenum, M66592_PIPESEL);
2064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_PIPECFG);
2074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0) {
2084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEBUF);
2094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = ((tmp >> 10) + 1) * 64;
2104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
2114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEMAXP);
2124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MXPS;
2134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return size;
2174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_change(struct m66592 *m66592, u16 pipenum)
2204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
2222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned short mbw;
2234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
2254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
2284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ndelay(450);
2304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip)
2322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		mbw = M66592_MBW_32;
2332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	else
2342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		mbw = M66592_MBW_16;
2352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
2362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592_bset(m66592, mbw, ep->fifosel);
2374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int pipe_buffer_setting(struct m66592 *m66592,
240598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_pipe_info *info)
2414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 bufnum = 0, buf_bsize = 0;
2434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipecfg = 0;
2444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
2474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->pipe, M66592_PIPESEL);
2494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->dir_in)
2514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DIR;
2524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->type;
2534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->epnum;
2544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (info->type) {
2554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_INT:
2564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
2574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 0;
2584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_BULK:
2604048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		/* isochronous pipes may be used as bulk pipes */
261108be95f9ffc53660c9a35b5ceef94121b1e23c4Yusuke Goda		if (info->pipe >= M66592_BASE_PIPENUM_BULK)
2624048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm			bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
2634048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		else
2644048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm			bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
2654048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm
2664048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
2674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DBLB;
2694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (!info->dir_in)
2704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipecfg |= M66592_SHTNAK;
2714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_ISO:
2734048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		bufnum = M66592_BASE_BUFNUM +
2744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
2754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2784048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm
2794048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm	if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
2804048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		pr_err("m66592 pipe memory is insufficient\n");
2814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENOMEM;
2824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, pipecfg, M66592_PIPECFG);
2854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
2864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
2874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->interval)
2884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info->interval--;
2894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->interval, M66592_PIPEPERI);
2904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
2924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_buffer_release(struct m66592 *m66592,
2954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				struct m66592_pipe_info *info)
2964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (is_bulk_pipe(info->pipe)) {
3014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk--;
3024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else if (is_interrupt_pipe(info->pipe))
3034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->interrupt--;
3044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (is_isoc_pipe(info->pipe)) {
3054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->isochronous--;
3064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (info->type == M66592_BULK)
3074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->bulk--;
3084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
30900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ep_release: unexpect pipenum (%d)\n",
310598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info->pipe);
3114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_initialize(struct m66592_ep *ep)
3144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3162c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned short mbw;
3174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
3194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_ACLRM, ep->pipectr);
3214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, 0, ep->pipectr);
3224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_SQCLR, ep->pipectr);
3234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma) {
3244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
3254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(450);
3274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3282c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->on_chip)
3292c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			mbw = M66592_MBW_32;
3302c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
3312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			mbw = M66592_MBW_16;
3322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
3332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, mbw, ep->fifosel);
3344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
338598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc,
339598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pipenum, int dma)
3404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((pipenum != 0) && dma) {
3424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->num_dma == 0) {
3434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D0FIFO;
3464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D0FIFOSEL;
3474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D0FIFOCTR;
3484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D0FIFOTRN;
3492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		} else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
3504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D1FIFO;
3534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D1FIFOSEL;
3544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D1FIFOCTR;
3554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D1FIFOTRN;
3564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
3574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 0;
3584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_CFIFO;
3594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_CFIFOSEL;
3604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_CFIFOCTR;
3614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = 0;
3624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
3634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
3644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->use_dma = 0;
3654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoaddr = M66592_CFIFO;
3664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifosel = M66592_CFIFOSEL;
3674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoctr = M66592_CFIFOCTR;
3684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifotrn = 0;
3694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipectr = get_pipectr_addr(pipenum);
3724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = pipenum;
373598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
3744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[pipenum] = ep;
3754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
3764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&ep->queue);
3774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_release(struct m66592_ep *ep)
3804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
3834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
3854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
3864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
3884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->num_dma--;
3894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = 0;
3904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->busy = 0;
3914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->use_dma = 0;
3924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int alloc_pipe_config(struct m66592_ep *ep,
395598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc)
3964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
3994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int dma = 0;
4004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int *counter;
4014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret;
4024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->desc = desc;
4044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(ep->pipenum);
4064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
407598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
4084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_BULK:
4094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
4104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
41100274921a052d3232d9f00856387fb269ac0af11David Brownell				pr_err("bulk pipe is insufficient\n");
4124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				return -ENODEV;
4134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
414598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info.pipe = M66592_BASE_PIPENUM_ISOC
415598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda						+ m66592->isochronous;
4164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				counter = &m66592->isochronous;
4174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
4184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
4194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
4204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			counter = &m66592->bulk;
4214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_BULK;
4234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		dma = 1;
4244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_INT:
4264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
42700274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("interrupt pipe is insufficient\n");
4284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
4314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_INT;
4324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->interrupt;
4334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_ISOC:
4354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
43600274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("isochronous pipe is insufficient\n");
4374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
4404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_ISO;
4414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->isochronous;
4424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
44400274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect xfer type\n");
4454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
4464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->type = info.type;
4484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
450598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
4514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.interval = desc->bInterval;
4524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
4534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 1;
4544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
4554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 0;
4564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ret = pipe_buffer_setting(m66592, &info);
4584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
45900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("pipe_buffer_setting fail\n");
4604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return ret;
4614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	(*counter)++;
4644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
4654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk++;
4664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
4684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_initialize(ep);
4694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int free_pipe_config(struct m66592_ep *ep)
4744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
4764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
4774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.pipe = ep->pipenum;
4794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.type = ep->type;
4804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_buffer_release(m66592, &info);
4814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_release(ep);
4824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
4874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
4884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_ready(m66592, pipenum);
4904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_nrdy(m66592, pipenum);
4914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
4944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_ready(m66592, pipenum);
4964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_nrdy(m66592, pipenum);
4974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if complete is true, gadget driver complete function is not call */
5004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void control_end(struct m66592 *m66592, unsigned ccpl)
5014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].internal_ccpl = ccpl;
5034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, 0);
5044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
5054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
5084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
513598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			(M66592_ISEL | M66592_CURPIPE),
514598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_CFIFOSEL);
5154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.length == 0) {
5174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
5184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, 0);
5194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
5204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
5224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
5234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
5274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
5304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_empty(m66592, ep->pipenum);
5334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, ep->pipenum);
5344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
5364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0))
5374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, ep->pipenum);
5384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_write(ep, req);
5404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
5434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
5464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->pipenum == 0) {
5484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0,
549598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(M66592_ISEL | M66592_CURPIPE),
550598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
5514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);
5534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->use_dma) {
5564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
5574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_change(m66592, pipenum);
5584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRENB, ep->fifosel);
5594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592,
560598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(req->req.length + ep->ep.maxpacket - 1)
561598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					/ ep->ep.maxpacket,
562598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				ep->fifotrn);
5634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
5644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);	/* trigger once */
5654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet(struct m66592_ep *ep, struct m66592_request *req)
5704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->desc->bEndpointAddress & USB_DIR_IN)
5724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_write(ep, req);
5734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
5784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
5804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
5824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
5844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
5854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0_write(ep, req);
5864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
5884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
5924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(ep->m66592, 0);
5934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
59500274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
5964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6008c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimodastatic void init_controller(struct m66592 *m66592)
6018c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda{
6022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned int endian;
6038c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6042c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
6052c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->endian)
6062c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = 0; /* big endian */
6072c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6082c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = M66592_LITTLE; /* little endian */
6098c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
6112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6132c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6148c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6152c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		/* This is a workaound for SH7722 2nd cut */
6162c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
6172c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, 0x1000, M66592_TESTMODE);
6182c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
6194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6202c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
6212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, 0, M66592_CFBCFG);
6232c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, 0, M66592_D0FBCFG);
6242c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, endian, M66592_CFBCFG);
6252c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, endian, M66592_D0FBCFG);
6262c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	} else {
6272c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		unsigned int clock, vif, irq_sense;
6282c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6292c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->endian)
6302c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = M66592_BIGEND; /* big endian */
6312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = 0; /* little endian */
6332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->vif)
6352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			vif = M66592_LDRV; /* 3.3v */
6362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6372c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			vif = 0; /* 1.5v */
6382c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6392c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		switch (m66592->pdata->xtal) {
6402c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_12MHZ:
6412c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL12;
6422c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6432c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_24MHZ:
6442c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL24;
6452c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6462c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_48MHZ:
6472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL48;
6482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		default:
6502c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			pr_warning("m66592-udc: xtal configuration error\n");
6512c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = 0;
6522c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
6534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6542c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		switch (m66592->irq_trigger) {
6552c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case IRQF_TRIGGER_LOW:
6562c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = M66592_INTL;
6572c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6582c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case IRQF_TRIGGER_FALLING:
6592c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = 0;
6602c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6612c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		default:
6622c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			pr_warning("m66592-udc: irq trigger config error\n");
6632c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = 0;
6642c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
6654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6662c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592,
6672c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    (vif & M66592_LDRV) | (endian & M66592_BIGEND),
6682c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    M66592_PINCFG);
6692c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
6702c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
6712c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    M66592_SYSCFG);
6722c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6732c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6742c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6762c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
6772c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6782c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		msleep(3);
6794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6802c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
6814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6822c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		msleep(1);
6834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6842c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
6852c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6862c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
6872c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
6882c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			     M66592_DMA0CFG);
6892c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
6904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592)
6934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
6942c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!m66592->pdata->on_chip) {
6952c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
6962c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
6972c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
6982c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
6992c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
7002c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
7012c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
7022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
7034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_start_xclock(struct m66592 *m66592)
7064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
7084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7092c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!m66592->pdata->on_chip) {
7102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		tmp = m66592_read(m66592, M66592_SYSCFG);
7112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (!(tmp & M66592_XCKE))
7122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
7132c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
7144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
7174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
718598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status)
719598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
720598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
7214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int restart = 0;
7234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely(ep->pipenum == 0)) {
7254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->internal_ccpl) {
7264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->internal_ccpl = 0;
7274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_del_init(&req->queue);
7324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
7334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -ESHUTDOWN;
7344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
7354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = status;
7364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
7384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		restart = 1;
7394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
740598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&ep->m66592->lock);
741598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	req->req.complete(&ep->ep, &req->req);
742598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&ep->m66592->lock);
7434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (restart) {
7454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
7464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->desc)
7474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
7484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
7524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
754598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 tmp;
7554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
7564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
7574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
7584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
7594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
7604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
7624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_ISEL, ep->fifosel);
7634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	i = 0;
7654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	do {
7664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, ep->fifoctr);
7674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i++ > 100000) {
76800274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("pipe0 is busy. maybe cpu i/o bus "
7694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				"conflict. please power off this controller.");
7704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(1);
7734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} while ((tmp & M66592_FRDY) == 0);
7744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
7764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
7774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
7784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
7794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
7814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
7824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size > 0)
7834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
7844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
7854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
7864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
7894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
7904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
792598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
793598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
794598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
7954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
7974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
7984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
8004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, pipenum);
8024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
8054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
8074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
8084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
8094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
81800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("write fifo not ready. pipnum=%d\n", pipenum);
8194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
8264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
8284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
8294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
830598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((size == 0)
831598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((size % ep->ep.maxpacket) != 0)
832598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((bufsize != ep->ep.maxpacket)
833598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&& (bufsize > size)))
8344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
8354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
840598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
841598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
842598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
8444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
8454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
8464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
8474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
8484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
8524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
8544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int rcv_len, bufsize, req_len;
8554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
8564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int finish = 0;
8604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -EPIPE;
8654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
86700274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("read fifo not ready");
8684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	rcv_len = tmp & M66592_DTLN;
8734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req_len = req->req.length - req->req.actual;
8774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (rcv_len < bufsize)
8784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(rcv_len, req_len);
8794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
8804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(bufsize, req_len);
8814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
886598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
887598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
888598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
8914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		finish = 1;
8924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
8954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
8964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size == 0)
8974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592, M66592_BCLR, ep->fifoctr);
8984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
8994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
9004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ep->pipenum != 0) && finish)
9034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
9044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
9074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
9144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
9154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
916598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
9174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_read(ep, req);
9214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BRDYSTS);
9264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				ep = m66592->pipenum2ep[pipenum];
9274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				req = list_entry(ep->queue.next,
9284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						 struct m66592_request, queue);
9294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (ep->desc->bEndpointAddress & USB_DIR_IN)
9304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_write(ep, req);
9314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
9324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_read(ep, req);
9334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
9394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
9414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
9474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
9484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
9524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BEMPSTS);
9574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				tmp = control_reg_get(m66592, pipenum);
9584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if ((tmp & M66592_INBUFM) == 0) {
9594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					disable_irq_empty(m66592, pipenum);
9604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_irq_disable(m66592, pipenum);
9614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_stop(m66592, pipenum);
9624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					ep = m66592->pipenum2ep[pipenum];
9634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					req = list_entry(ep->queue.next,
9644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 struct m66592_request,
9654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 queue);
9664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					if (!list_empty(&ep->queue))
9674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						transfer_complete(ep, req, 0);
9684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				}
9694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
975598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
976598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
9774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid;
9804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 status = 0;
981598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 w_index = le16_to_cpu(ctrl->wIndex);
9824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
9844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
985598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		status = 1 << USB_DEVICE_SELF_POWERED;
9864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
9884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		status = 0;
9894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT:
991598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
9924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = control_reg_get_pid(m66592, ep->pipenum);
9934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (pid == M66592_PID_STALL)
994598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			status = 1 << USB_ENDPOINT_HALT;
9954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
9964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			status = 0;
9974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
9994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;		/* exit */
10014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1003598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_data = cpu_to_le16(status);
1004598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->buf = &m66592->ep0_data;
10054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req->length = 2;
100653b67950026ee642b43615f46df22ec3d36b4a53Al Viro	/* AV: what happens if we get called again before that gets through? */
1007598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
10084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
1009598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
10104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
10164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
10234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
1024598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1026598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, ep->pipenum);
10284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_reg_sqclr(m66592, ep->pipenum);
10294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next,
10334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request, queue);
10344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->busy) {
10354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->busy = 0;
10364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (list_empty(&ep->queue))
10374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				break;
10384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
10394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else if (!list_empty(&ep->queue))
10404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_start(m66592, ep->pipenum);
10414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
10544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
1061598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1063598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, ep->pipenum);
10654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if return value is true, call class driver's setup() */
10764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 *p = (u16 *)ctrl;
10794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset = M66592_USBREQ;
10804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i, ret = 0;
10814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
10834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
10844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < 4; i++)
10864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		p[i] = m66592_read(m66592, offset + i*2);
10874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check request */
10894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
10904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		switch (ctrl->bRequest) {
10914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_GET_STATUS:
10924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			get_status(m66592, ctrl);
10934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
10944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_CLEAR_FEATURE:
10954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			clear_feature(m66592, ctrl);
10964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
10974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_SET_FEATURE:
10984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			set_feature(m66592, ctrl);
10994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		default:
11014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ret = 1;
11024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
11054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = 1;
11064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
11074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_update_usb_speed(struct m66592 *m66592)
11104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 speed = get_usb_speed(m66592);
11124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (speed) {
11144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_HSMODE:
11154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_HIGH;
11164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_FSMODE:
11184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_FULL;
11194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
11214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_UNKNOWN;
112200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("USB speed unknown\n");
11234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_device_state(struct m66592 *m66592)
11274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 dvsq;
11294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
11314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
11324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (dvsq == M66592_DS_DFLT) {	/* bus reset */
11344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->driver->disconnect(&m66592->gadget);
11354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
11384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
1139598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
1140598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			&& m66592->gadget.speed == USB_SPEED_UNKNOWN)
11414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->old_dvsq = dvsq;
11444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_control_stage(struct m66592 *m66592)
1147598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
1148598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
11494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct usb_ctrlrequest ctrl;
11514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
11524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
11544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
11554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
11574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_IDST: {
11584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
11594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
11604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
11614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
11624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
11634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
11674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
11684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
11694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (setup_packet(m66592, &ctrl)) {
1170598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_unlock(&m66592->lock);
11714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
11724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				pipe_stall(m66592, 0);
1173598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_lock(&m66592->lock);
11744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDSS:
11774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRSS:
11784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 0);
11794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
118100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
11824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic irqreturn_t m66592_irq(int irq, void *_m66592)
11874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = _m66592;
11894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intsts0;
11904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intenb0;
11914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdysts, nrdysts, bempsts;
11924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdyenb, nrdyenb, bempenb;
11934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 savepipe;
11944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 mask0;
11954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1196598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
1197598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
11984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intsts0 = m66592_read(m66592, M66592_INTSTS0);
11994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intenb0 = m66592_read(m66592, M66592_INTENB0);
12004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12012c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
12028c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		/*
12038c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * When USB clock stops, it cannot read register. Even if a
12048c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * clock stops, the interrupt occurs. So this driver turn on
12058c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * a clock by this timing and do re-reading of register.
12068c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 */
12078c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		m66592_start_xclock(m66592);
12088c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intsts0 = m66592_read(m66592, M66592_INTSTS0);
12098c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intenb0 = m66592_read(m66592, M66592_INTENB0);
12108c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	}
12118c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
12124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
12134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	mask0 = intsts0 & intenb0;
12154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (mask0) {
12164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdysts = m66592_read(m66592, M66592_BRDYSTS);
12174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdysts = m66592_read(m66592, M66592_NRDYSTS);
12184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempsts = m66592_read(m66592, M66592_BEMPSTS);
12194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdyenb = m66592_read(m66592, M66592_BRDYENB);
12204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdyenb = m66592_read(m66592, M66592_NRDYENB);
12214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempenb = m66592_read(m66592, M66592_BEMPENB);
12224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (mask0 & M66592_VBINT) {
1224598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			m66592_write(m66592,  0xffff & ~M66592_VBINT,
1225598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					M66592_INTSTS0);
12264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_start_xclock(m66592);
12274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			/* start vbus sampling */
12294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
1230598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					& M66592_VBSTS;
12314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1234598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_DVSQ)
12374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_device_state(m66592);
12384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1239598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
1240598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (brdysts & brdyenb)) {
12414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_ready(m66592, brdysts, brdyenb);
12424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
1243598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
1244598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (bempsts & bempenb)) {
12454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_empty(m66592, bempsts, bempenb);
12464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_CTRT)
12494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_control_stage(m66592);
12504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, savepipe, M66592_CFIFOSEL);
12534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1254598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
12554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return IRQ_HANDLED;
12564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_timer(unsigned long _m66592)
12594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = (struct m66592 *)_m66592;
12614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
12624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
12634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
12654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_SYSCFG);
12664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!(tmp & M66592_RCKE)) {
12674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
12684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		udelay(10);
12694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
12704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->scount > 0) {
12724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
12734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (tmp == m66592->old_vbus) {
12744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount--;
12754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->scount == 0) {
12764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (tmp == M66592_VBSTS)
12774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_connect(m66592);
12784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
12794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_disconnect(m66592);
12804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
12814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				mod_timer(&m66592->timer,
1282598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
12844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
12854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = tmp;
12874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1288598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
12924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
12954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_enable(struct usb_ep *_ep,
12964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 const struct usb_endpoint_descriptor *desc)
12974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
12994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return alloc_pipe_config(ep, desc);
13024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_disable(struct usb_ep *_ep)
13054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(!ep);
13124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	while (!list_empty(&ep->queue)) {
13144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
13154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_lock_irqsave(&ep->m66592->lock, flags);
13164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
13174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_unlock_irqrestore(&ep->m66592->lock, flags);
13184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_irq_disable(ep->m66592, ep->pipenum);
13214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return free_pipe_config(ep);
13224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
13254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						gfp_t gfp_flags)
13264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = kzalloc(sizeof(struct m66592_request), gfp_flags);
13304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!req)
13314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return NULL;
13324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&req->queue);
13344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return &req->req;
13364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
13394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(req);
13444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
13474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags)
13484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int request = 0;
13534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
13584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ESHUTDOWN;
13594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue))
13634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		request = 1;
13644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_add_tail(&req->queue, &ep->queue);
13664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual = 0;
13674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.status = -EINPROGRESS;
13684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1369a9475226977917afd5a85621f8a3d7f380a9da31David Brownell	if (ep->desc == NULL)	/* control */
13704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0(ep, req);
13714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else {
13724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (request && !ep->busy)
13734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
13744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
13774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
13794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
13824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
13924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
13934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
13944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
13964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_set_halt(struct usb_ep *_ep, int value)
13994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
14024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
14044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = list_entry(ep->queue.next, struct m66592_request, queue);
14074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue)) {
14104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -EAGAIN;
14114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto out;
14124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (value) {
14144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 1;
14154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(ep->m66592, ep->pipenum);
14164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
14174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 0;
14184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaout:
14224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
14244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_fifo_flush(struct usb_ep *_ep)
14274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue) && !ep->busy) {
14344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
14364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_ep_ops m66592_ep_ops = {
14414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.enable		= m66592_enable,
14424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.disable	= m66592_disable,
14434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.alloc_request	= m66592_alloc_request,
14454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.free_request	= m66592_free_request,
14464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.queue		= m66592_queue,
14484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.dequeue	= m66592_dequeue,
14494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.set_halt	= m66592_set_halt,
14514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.fifo_flush	= m66592_fifo_flush,
14524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
14534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
14554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct m66592 *the_controller;
14564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14570f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorstatic int m66592_start(struct usb_gadget_driver *driver,
1458b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König		int (*bind)(struct usb_gadget *))
14594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
14614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int retval;
14624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1463598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (!driver
1464598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| driver->speed != USB_SPEED_HIGH
1465b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König			|| !bind
1466598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| !driver->setup)
14674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
14684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!m66592)
14694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENODEV;
14704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->driver)
14714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EBUSY;
14724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* hook up the driver */
14744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->driver.bus = NULL;
14754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = driver;
14764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = &driver->driver;
14774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	retval = device_add(&m66592->gadget.dev);
14794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
148000274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("device_add error (%d)\n", retval);
14814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
14824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1484b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König	retval = bind(&m66592->gadget);
14854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
148600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("bind to driver error (%d)\n", retval);
14874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		device_del(&m66592->gadget.dev);
14884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
14894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
14924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
14934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_start_xclock(m66592);
14944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		/* start vbus sampling */
14954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->old_vbus = m66592_read(m66592,
14964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					 M66592_INTSTS0) & M66592_VBSTS;
14974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->scount = M66592_MAX_SAMPLING;
1498598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
14994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaerror:
15044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = NULL;
15064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return retval;
15084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15100f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorstatic int m66592_stop(struct usb_gadget_driver *driver)
15114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
15134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
15144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1515598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (driver != m66592->driver || !driver->unbind)
1516598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		return -EINVAL;
1517598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
15194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
15204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_usb_disconnect(m66592);
15214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
15224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
15244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->unbind(&m66592->gadget);
1526eb0be47dbbdca133b1b94adc564297f25176b3abPatrik Sevallius	m66592->gadget.dev.driver = NULL;
15274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
15294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
15304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_del(&m66592->gadget.dev);
15324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
15374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_get_frame(struct usb_gadget *_gadget)
15384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = gadget_to_m66592(_gadget);
15404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
15414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_gadget_ops m66592_gadget_ops = {
15444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.get_frame		= m66592_get_frame,
15450f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	.start			= m66592_start,
15460f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	.stop			= m66592_stop,
15474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
15484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1549598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic int __exit m66592_remove(struct platform_device *pdev)
15504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
15524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15530f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	usb_del_gadget_udc(&m66592->gadget);
15540f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
15554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	del_timer_sync(&m66592->timer);
15564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	iounmap(m66592->reg);
15574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	free_irq(platform_get_irq(pdev, 0), m66592);
1558598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
15592c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
15602c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
15612c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_disable(m66592->clk);
15622c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_put(m66592->clk);
15632c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
1564af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
15654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(m66592);
15664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1569598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic void nop_completion(struct usb_ep *ep, struct usb_request *r)
1570598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda{
1571598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda}
1572598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_probe(struct platform_device *pdev)
15744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15752c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	struct resource *res, *ires;
15764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void __iomem *reg = NULL;
15774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = NULL;
15782c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
1579af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm	char clk_name[8];
1580af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
15814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
15824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
15834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15840a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
15854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!res) {
15864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
15870a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm		pr_err("platform_get_resource error.\n");
15884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
15894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15912c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
15922c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!ires) {
15934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
15942c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		dev_err(&pdev->dev,
15952c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			"platform_get_resource IORESOURCE_IRQ error.\n");
15964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
15974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15990a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm	reg = ioremap(res->start, resource_size(res));
16004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg == NULL) {
16014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENOMEM;
160200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ioremap error.\n");
16034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16062c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (pdev->dev.platform_data == NULL) {
16072c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		dev_err(&pdev->dev, "no platform data\n");
16082c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		ret = -ENODEV;
16092c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		goto clean_up;
16102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
16112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
16124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* initialize ucd */
16134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
16144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592 == NULL) {
16157c81aafaf059b81ead2330bc13db78269ef62612Julia Lawall		ret = -ENOMEM;
161600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("kzalloc error\n");
16174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16202c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592->pdata = pdev->dev.platform_data;
16212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
16222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
16234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_init(&m66592->lock);
16244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dev_set_drvdata(&pdev->dev, m66592);
16254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ops = &m66592_gadget_ops;
16274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_initialize(&m66592->gadget.dev);
1628836e4b14b41d19d17341a2dd2c49af8dd54e3aacPaul Mundt	dev_set_name(&m66592->gadget.dev, "gadget");
16294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.is_dualspeed = 1;
16304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.parent = &pdev->dev;
16314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
16324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.release = pdev->dev.release;
16334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.name = udc_name;
16344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_timer(&m66592->timer);
16364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.function = m66592_timer;
16374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.data = (unsigned long)m66592;
16384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->reg = reg;
16394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16402c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	ret = request_irq(ires->start, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
1641598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			udc_name, m66592);
16424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
164300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("request_irq error (%d)\n", ret);
16444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
16482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
16492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
16502c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592->clk = clk_get(&pdev->dev, clk_name);
16512c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (IS_ERR(m66592->clk)) {
16522c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
16532c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm				clk_name);
16542c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			ret = PTR_ERR(m66592->clk);
16552c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			goto clean_up2;
16562c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
16572c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_enable(m66592->clk);
1658af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm	}
1659af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
16604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep_list);
16614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ep0 = &m66592->ep[0].ep;
16624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
16634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
16644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep = &m66592->ep[i];
16654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i != 0) {
16674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
16684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			list_add_tail(&m66592->ep[i].ep.ep_list,
1669598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&m66592->gadget.ep_list);
16704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
16714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->m66592 = m66592;
16724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		INIT_LIST_HEAD(&ep->queue);
16734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.name = m66592_ep_name[i];
16744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.ops = &m66592_ep_ops;
16754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.maxpacket = 512;
16764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].ep.maxpacket = 64;
16784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipenum = 0;
16794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoaddr = M66592_CFIFO;
16804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifosel = M66592_CFIFOSEL;
16814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoctr = M66592_CFIFOCTR;
16824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifotrn = 0;
16834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipectr = get_pipectr_addr(0);
16844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[0] = &m66592->ep[0];
16854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[0] = &m66592->ep[0];
16864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	the_controller = m66592;
16884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
16904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->ep0_req == NULL)
1691af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm		goto clean_up3;
1692598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->complete = nop_completion;
16934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
16954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16960f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
16970f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	if (ret)
16980f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior		goto err_add_udc;
16990f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
1700598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
17014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
17024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17030f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorerr_add_udc:
17040f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
17050f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
1706af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Dammclean_up3:
17072c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
17082c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
17092c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_disable(m66592->clk);
17102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_put(m66592->clk);
17112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
1712598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodaclean_up2:
1713d6435102d4ca3b5655c0105abe924abec17ffeb8Paul Mundt#endif
17142c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	free_irq(ires->start, m66592);
17154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaclean_up:
17164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592) {
17174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->ep0_req)
17184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
17194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		kfree(m66592);
17204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
17214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg)
17224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		iounmap(reg);
17234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
17254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
17284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct platform_driver m66592_driver = {
1729598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	.remove =	__exit_p(m66592_remove),
17304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.driver		= {
17314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		.name =	(char *) udc_name,
1732f34c32f13ce8c539f3f582562358e39a86b00e83Kay Sievers		.owner	= THIS_MODULE,
17334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	},
17344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
17354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_udc_init(void)
17374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1738598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	return platform_driver_probe(&m66592_driver, m66592_probe);
17394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_init(m66592_udc_init);
17414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void __exit m66592_udc_cleanup(void)
17434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
17444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	platform_driver_unregister(&m66592_driver);
17454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_exit(m66592_udc_cleanup);
1747