14cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*
24cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * M66592 UDC (USB gadget)
34cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
44cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * Copyright (C) 2006-2007 Renesas Solutions Corp.
54cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
65db05c09ac107ef957b7a052d7bba8190c93b460Yoshihiro Shimoda * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
74cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda *
84cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * This program is free software; you can redistribute it and/or modify
94cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * it under the terms of the GNU General Public License as published by
104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda * the Free Software Foundation; version 2 of the License.
114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda */
124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/module.h>
144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/interrupt.h>
15598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda#include <linux/delay.h>
16598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda#include <linux/io.h>
174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/platform_device.h>
185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
1956fd1260a8de3738034588c6e32262960c5b2660Paul Mundt#include <linux/err.h>
204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include <linux/usb/ch9.h>
219454a57ab5922e5cd25321cae9d1a8cbeb3e2e85David Brownell#include <linux/usb/gadget.h>
224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda#include "m66592-udc.h"
244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
25598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro ShimodaMODULE_DESCRIPTION("M66592 USB gadget driver");
264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaMODULE_LICENSE("GPL");
274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro ShimodaMODULE_AUTHOR("Yoshihiro Shimoda");
28f34c32f13ce8c539f3f582562358e39a86b00e83Kay SieversMODULE_ALIAS("platform:m66592_udc");
294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
302c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#define DRIVER_VERSION	"21 July 2009"
314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char udc_name[] = "m66592_udc";
334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic const char *m66592_ep_name[] = {
344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	"ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592);
384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags);
424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
44598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status);
45598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 get_usb_speed(struct m66592 *m66592)
484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
53598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
59598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, (1 << pipenum), reg);
614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
65598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		unsigned long reg)
664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_INTENB0);
704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
71598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, (1 << pipenum), reg);
734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, tmp, M66592_INTENB0);
744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_connect(struct m66592 *m66592)
774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
80598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_usb_disconnect(struct m66592 *m66592)
87598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
88598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
92598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_INTENB0);
934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.speed = USB_SPEED_UNKNOWN;
974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock(&m66592->lock);
984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver->disconnect(&m66592->gadget);
994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock(&m66592->lock);
1004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
1024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->ep[0].queue);
1034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
1064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid = 0;
1084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
1124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = m66592_read(m66592, offset) & M66592_PID;
1154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
11600274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return pid;
1194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
122598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pid)
1234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
1284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, pid, M66592_PID, offset);
1314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
13200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_start(struct m66592 *m66592, u16 pipenum)
1364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
1384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
1414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
1434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
1464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
1484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
1514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ret = 0;
1534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, M66592_DCPCTR);
1574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = m66592_read(m66592, offset);
1604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
16100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num (%d)\n", pipenum);
1624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
1644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
1674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset;
1694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_stop(m66592, pipenum);
1714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
1734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
1744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (pipenum < M66592_MAX_NUM_PIPE) {
1754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		offset = get_pipectr_addr(pipenum);
1764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SQCLR, offset);
1774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
17800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect pipe num(%d)\n", pipenum);
1794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
1804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
1824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
1844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
1854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0) {
1874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_DCPCFG);
1884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0)
1894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = 256;
1904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else {
1914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_DCPMAXP);
1924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MAXP;
1934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
1944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
1954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, pipenum, M66592_PIPESEL);
1964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_PIPECFG);
1974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((tmp & M66592_CNTMD) != 0) {
1984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEBUF);
1994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = ((tmp >> 10) + 1) * 64;
2004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
2014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			tmp = m66592_read(m66592, M66592_PIPEMAXP);
2024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			size = tmp & M66592_MXPS;
2034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
2044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return size;
2074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic inline void pipe_change(struct m66592 *m66592, u16 pipenum)
2104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
2122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned short mbw;
2134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
2154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
2184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ndelay(450);
2204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip)
2222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		mbw = M66592_MBW_32;
2232c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	else
2242c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		mbw = M66592_MBW_16;
2252c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
2262c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592_bset(m66592, mbw, ep->fifosel);
2274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int pipe_buffer_setting(struct m66592 *m66592,
230598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_pipe_info *info)
2314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 bufnum = 0, buf_bsize = 0;
2334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipecfg = 0;
2344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
2374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->pipe, M66592_PIPESEL);
2394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->dir_in)
2414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DIR;
2424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->type;
2434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipecfg |= info->epnum;
2444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (info->type) {
2454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_INT:
2464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
2474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 0;
2484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_BULK:
2504048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		/* isochronous pipes may be used as bulk pipes */
251108be95f9ffc53660c9a35b5ceef94121b1e23c4Yusuke Goda		if (info->pipe >= M66592_BASE_PIPENUM_BULK)
2524048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm			bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
2534048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		else
2544048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm			bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
2554048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm
2564048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		bufnum = M66592_BASE_BUFNUM + (bufnum * 16);
2574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipecfg |= M66592_DBLB;
2594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (!info->dir_in)
2604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipecfg |= M66592_SHTNAK;
2614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_ISO:
2634048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		bufnum = M66592_BASE_BUFNUM +
2644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
2654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		buf_bsize = 7;
2664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
2674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2684048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm
2694048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm	if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) {
2704048e5ca29afbd747a16245f2bc4d1d521a6d0d0Magnus Damm		pr_err("m66592 pipe memory is insufficient\n");
2714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENOMEM;
2724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
2734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, pipecfg, M66592_PIPECFG);
2754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
2764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
2774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->interval)
2784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info->interval--;
2794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, info->interval, M66592_PIPEPERI);
2804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
2824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
2834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_buffer_release(struct m66592 *m66592,
2854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				struct m66592_pipe_info *info)
2864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
2874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (info->pipe == 0)
2884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
2894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
2904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (is_bulk_pipe(info->pipe)) {
2914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk--;
2924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else if (is_interrupt_pipe(info->pipe))
2934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->interrupt--;
2944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else if (is_isoc_pipe(info->pipe)) {
2954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->isochronous--;
2964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (info->type == M66592_BULK)
2974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->bulk--;
2984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
29900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ep_release: unexpect pipenum (%d)\n",
300598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info->pipe);
3014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_initialize(struct m66592_ep *ep)
3044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3062c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned short mbw;
3074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
3094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_ACLRM, ep->pipectr);
3114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, 0, ep->pipectr);
3124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_SQCLR, ep->pipectr);
3134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma) {
3144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
3154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(450);
3174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3182c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->on_chip)
3192c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			mbw = M66592_MBW_32;
3202c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
3212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			mbw = M66592_MBW_16;
3222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
3232c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, mbw, ep->fifosel);
3244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
328598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc,
329598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 pipenum, int dma)
3304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((pipenum != 0) && dma) {
3324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->num_dma == 0) {
3334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D0FIFO;
3364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D0FIFOSEL;
3374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D0FIFOCTR;
3384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D0FIFOTRN;
3392c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		} else if (!m66592->pdata->on_chip && m66592->num_dma == 1) {
3404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->num_dma++;
3414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 1;
3424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_D1FIFO;
3434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_D1FIFOSEL;
3444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_D1FIFOCTR;
3454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = M66592_D1FIFOTRN;
3464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
3474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->use_dma = 0;
3484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoaddr = M66592_CFIFO;
3494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifosel = M66592_CFIFOSEL;
3504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifoctr = M66592_CFIFOCTR;
3514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->fifotrn = 0;
3524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
3534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
3544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->use_dma = 0;
3554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoaddr = M66592_CFIFO;
3564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifosel = M66592_CFIFOSEL;
3574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifoctr = M66592_CFIFOCTR;
3584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->fifotrn = 0;
3594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
3604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipectr = get_pipectr_addr(pipenum);
3624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = pipenum;
36329cc88979a8818cd8c5019426e945aed118b400eKuninori Morimoto	ep->ep.maxpacket = usb_endpoint_maxp(desc);
3644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[pipenum] = ep;
3654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
3664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&ep->queue);
3674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_ep_release(struct m66592_ep *ep)
3704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
3734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (pipenum == 0)
3754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
3764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->use_dma)
3784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->num_dma--;
3794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->pipenum = 0;
3804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->busy = 0;
3814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->use_dma = 0;
3824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
3834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int alloc_pipe_config(struct m66592_ep *ep,
385598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		const struct usb_endpoint_descriptor *desc)
3864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
3874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
3884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
3894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int dma = 0;
3904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int *counter;
3914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret;
3924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->desc = desc;
3944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
3954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(ep->pipenum);
3964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
397598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
3984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_BULK:
3994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
4004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
40100274921a052d3232d9f00856387fb269ac0af11David Brownell				pr_err("bulk pipe is insufficient\n");
4024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				return -ENODEV;
4034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
404598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				info.pipe = M66592_BASE_PIPENUM_ISOC
405598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda						+ m66592->isochronous;
4064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				counter = &m66592->isochronous;
4074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
4084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
4094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
4104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			counter = &m66592->bulk;
4114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_BULK;
4134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		dma = 1;
4144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_INT:
4164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
41700274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("interrupt pipe is insufficient\n");
4184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
4214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_INT;
4224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->interrupt;
4234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_ENDPOINT_XFER_ISOC:
4254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
42600274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("isochronous pipe is insufficient\n");
4274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return -ENODEV;
4284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
4294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
4304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.type = M66592_ISO;
4314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		counter = &m66592->isochronous;
4324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
4334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
43400274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("unexpect xfer type\n");
4354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
4364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep->type = info.type;
4384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
44029cc88979a8818cd8c5019426e945aed118b400eKuninori Morimoto	info.maxpacket = usb_endpoint_maxp(desc);
4414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.interval = desc->bInterval;
4424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
4434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 1;
4444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
4454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		info.dir_in = 0;
4464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ret = pipe_buffer_setting(m66592, &info);
4484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
44900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("pipe_buffer_setting fail\n");
4504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return ret;
4514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
4524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	(*counter)++;
4544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
4554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->bulk++;
4564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
4584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_initialize(ep);
4594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int free_pipe_config(struct m66592_ep *ep)
4644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
4664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_pipe_info info;
4674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.pipe = ep->pipenum;
4694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	info.type = ep->type;
4704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_buffer_release(m66592, &info);
4714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_ep_release(ep);
4724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
4744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
4774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
4784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_ready(m66592, pipenum);
4804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	enable_irq_nrdy(m66592, pipenum);
4814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
4844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_ready(m66592, pipenum);
4864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_nrdy(m66592, pipenum);
4874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if complete is true, gadget driver complete function is not call */
4904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void control_end(struct m66592 *m66592, unsigned ccpl)
4914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].internal_ccpl = ccpl;
4934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, 0);
4944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
4954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
4964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
4974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
4984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
4994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
503598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			(M66592_ISEL | M66592_CURPIPE),
504598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			M66592_CFIFOSEL);
5054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.length == 0) {
5074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
5084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, 0);
5094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
5104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
5124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
5134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
5174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
5204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, ep->pipenum);
5224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_irq_empty(m66592, ep->pipenum);
5234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, ep->pipenum);
5244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
5264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0))
5274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, ep->pipenum);
5284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_write(ep, req);
5304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
5334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
5354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
5364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->pipenum == 0) {
5384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0,
539598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(M66592_ISEL | M66592_CURPIPE),
540598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
5414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, M66592_BCLR, ep->fifoctr);
5424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);
5434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
5454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->use_dma) {
5464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
5474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_change(m66592, pipenum);
5484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_TRENB, ep->fifosel);
5494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592,
550598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				(req->req.length + ep->ep.maxpacket - 1)
551598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					/ ep->ep.maxpacket,
552598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				ep->fifotrn);
5534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
5544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_start(m66592, pipenum);	/* trigger once */
5554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
5564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_packet(struct m66592_ep *ep, struct m66592_request *req)
5604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->desc->bEndpointAddress & USB_DIR_IN)
5624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_write(ep, req);
5634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
5644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
5684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
5694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
5704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
5724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
5744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
5754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0_write(ep, req);
5764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
5784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_packet_read(ep, req);
5794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
5824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(ep->m66592, 0);
5834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
58500274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
5864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
5874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
5884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
5894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
5908c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimodastatic void init_controller(struct m66592 *m66592)
5918c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda{
5922c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	unsigned int endian;
5938c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
5942c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
5952c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->endian)
5962c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = 0; /* big endian */
5972c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
5982c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = M66592_LITTLE; /* little endian */
5998c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6002c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
6012c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6032c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6048c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
6052c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		/* This is a workaound for SH7722 2nd cut */
6062c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
6072c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, 0x1000, M66592_TESTMODE);
6082c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
6094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6102c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
6112c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, 0, M66592_CFBCFG);
6132c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, 0, M66592_D0FBCFG);
6142c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, endian, M66592_CFBCFG);
6152c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, endian, M66592_D0FBCFG);
6162c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	} else {
6172c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		unsigned int clock, vif, irq_sense;
6182c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6192c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->endian)
6202c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = M66592_BIGEND; /* big endian */
6212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			endian = 0; /* little endian */
6232c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6242c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (m66592->pdata->vif)
6252c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			vif = M66592_LDRV; /* 3.3v */
6262c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		else
6272c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			vif = 0; /* 1.5v */
6282c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6292c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		switch (m66592->pdata->xtal) {
6302c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_12MHZ:
6312c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL12;
6322c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_24MHZ:
6342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL24;
6352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case M66592_PLATDATA_XTAL_48MHZ:
6372c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = M66592_XTAL48;
6382c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6392c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		default:
6402c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			pr_warning("m66592-udc: xtal configuration error\n");
6412c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			clock = 0;
6422c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
6434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6442c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		switch (m66592->irq_trigger) {
6452c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case IRQF_TRIGGER_LOW:
6462c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = M66592_INTL;
6472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		case IRQF_TRIGGER_FALLING:
6492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = 0;
6502c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			break;
6512c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		default:
6522c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			pr_warning("m66592-udc: irq trigger config error\n");
6532c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			irq_sense = 0;
6542c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
6554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6562c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592,
6572c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    (vif & M66592_LDRV) | (endian & M66592_BIGEND),
6582c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    M66592_PINCFG);
6592c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);	/* High spd */
6602c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL,
6612c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			    M66592_SYSCFG);
6622c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
6632c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
6642c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
6654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6662c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
6672c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6682c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		msleep(3);
6694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6702c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
6714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6722c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		msleep(1);
6734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6742c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
6752c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
6762c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
6772c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
6782c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			     M66592_DMA0CFG);
6792c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
6804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void disable_controller(struct m66592 *m66592)
6834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
684ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda	m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
6852c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!m66592->pdata->on_chip) {
6862c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
6872c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
6882c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
6892c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
6902c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
6912c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		udelay(1);
6922c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
6932c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
6944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
6954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
6964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_start_xclock(struct m66592 *m66592)
6974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
6984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
6994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7002c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!m66592->pdata->on_chip) {
7012c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		tmp = m66592_read(m66592, M66592_SYSCFG);
7022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (!(tmp & M66592_XCKE))
7032c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
7042c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
7054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
7084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void transfer_complete(struct m66592_ep *ep,
709598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		struct m66592_request *req, int status)
710598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
711598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
7124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int restart = 0;
7144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely(ep->pipenum == 0)) {
7164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->internal_ccpl) {
7174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->internal_ccpl = 0;
7184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_del_init(&req->queue);
7234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
7244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -ESHUTDOWN;
7254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
7264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = status;
7274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
7294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		restart = 1;
7304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
731598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&ep->m66592->lock);
732598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	req->req.complete(&ep->ep, &req->req);
733598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&ep->m66592->lock);
7344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (restart) {
7364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
7374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->desc)
7384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
7394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
7434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
745598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 tmp;
7464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
7474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
7484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
7494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
7504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
7514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
7534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_ISEL, ep->fifosel);
7544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	i = 0;
7564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	do {
7574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, ep->fifoctr);
7584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i++ > 100000) {
75900274921a052d3232d9f00856387fb269ac0af11David Brownell			pr_err("pipe0 is busy. maybe cpu i/o bus "
7604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				"conflict. please power off this controller.");
7614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			return;
7624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
7634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ndelay(1);
7644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} while ((tmp & M66592_FRDY) == 0);
7654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
7674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
7684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
7694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
7704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
7724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
7734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size > 0)
774bb59dbff4e5fb0ac14e3ee47d3f688490f128155Yoshihiro Shimoda			m66592_write_fifo(m66592, ep, buf, size);
7754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
7764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
7774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
7804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
7814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
783598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
784598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
785598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
7864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
7884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
7894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
7904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
7914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
7924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_start(m66592, pipenum);
7934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
7944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
7954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
7964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
7974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
7984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned bufsize;
7994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size_t size;
8004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
80900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("write fifo not ready. pipnum=%d\n", pipenum);
8104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	size = min(bufsize, req->req.length - req->req.actual);
8174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* write fifo */
8194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
820bb59dbff4e5fb0ac14e3ee47d3f688490f128155Yoshihiro Shimoda		m66592_write_fifo(m66592, ep, buf, size);
821598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((size == 0)
822598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((size % ep->ep.maxpacket) != 0)
823598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				|| ((bufsize != ep->ep.maxpacket)
824598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&& (bufsize > size)))
8254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
8264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
831598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
832598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
833598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_ready(m66592, pipenum);
8354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		enable_irq_empty(m66592, pipenum);
8364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
8374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		disable_irq_empty(m66592, pipenum);
8384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_enable(m66592, pipenum);
8394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
8434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
8454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int rcv_len, bufsize, req_len;
8464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int size;
8474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void *buf;
8484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum = ep->pipenum;
8494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = ep->m66592;
8504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int finish = 0;
8514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_change(m66592, pipenum);
8534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, ep->fifoctr);
8544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (unlikely((tmp & M66592_FRDY) == 0)) {
8554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req->req.status = -EPIPE;
8564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
85800274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("read fifo not ready");
8594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;
8604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* prepare parameters */
8634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	rcv_len = tmp & M66592_DTLN;
8644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	bufsize = get_buffer_size(m66592, pipenum);
8654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	buf = req->req.buf + req->req.actual;
8674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req_len = req->req.length - req->req.actual;
8684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (rcv_len < bufsize)
8694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(rcv_len, req_len);
8704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else
8714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		size = min(bufsize, req_len);
8724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* update parameters */
8744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual += size;
8754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check transfer finish */
877598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((!req->req.zero && (req->req.actual == req->req.length))
878598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size % ep->ep.maxpacket)
879598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| (size == 0)) {
8804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, pipenum);
8814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_irq_disable(m66592, pipenum);
8824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		finish = 1;
8834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
8864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (req->req.buf) {
8874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (size == 0)
8884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_write(m66592, M66592_BCLR, ep->fifoctr);
8894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
8904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
8914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
8924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ep->pipenum != 0) && finish)
8944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
8954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
8964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
8974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
8984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
8994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
9054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
9064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
907598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				M66592_CFIFOSEL);
9084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_packet_read(ep, req);
9124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BRDYSTS);
9174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				ep = m66592->pipenum2ep[pipenum];
9184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				req = list_entry(ep->queue.next,
9194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						 struct m66592_request, queue);
9204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (ep->desc->bEndpointAddress & USB_DIR_IN)
9214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_write(ep, req);
9224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
9234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					irq_packet_read(ep, req);
9244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
9304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
9324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 check;
9334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pipenum;
9344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
9364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
9384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
9394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
9414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
9424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		irq_ep0_write(ep, req);
9434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
9444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
9454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			check = 1 << pipenum;
9464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if ((status & check) && (enb & check)) {
9474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				m66592_write(m66592, ~check, M66592_BEMPSTS);
9484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				tmp = control_reg_get(m66592, pipenum);
9494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if ((tmp & M66592_INBUFM) == 0) {
9504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					disable_irq_empty(m66592, pipenum);
9514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_irq_disable(m66592, pipenum);
9524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					pipe_stop(m66592, pipenum);
9534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					ep = m66592->pipenum2ep[pipenum];
9544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					req = list_entry(ep->queue.next,
9554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 struct m66592_request,
9564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda							 queue);
9574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					if (!list_empty(&ep->queue))
9584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						transfer_complete(ep, req, 0);
9594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				}
9604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
9614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
9624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
9644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
966598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
967598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
9684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
9694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
9704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 pid;
9714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 status = 0;
972598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	u16 w_index = le16_to_cpu(ctrl->wIndex);
9734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
9744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
9754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
976598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		status = 1 << USB_DEVICE_SELF_POWERED;
9774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
9794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		status = 0;
9804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT:
982598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
9834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pid = control_reg_get_pid(m66592, ep->pipenum);
9844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (pid == M66592_PID_STALL)
985598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			status = 1 << USB_ENDPOINT_HALT;
9864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		else
9874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			status = 0;
9884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
9894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
9904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
9914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return;		/* exit */
9924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
9934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
994598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_data = cpu_to_le16(status);
995598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->buf = &m66592->ep0_data;
9964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req->length = 2;
99753b67950026ee642b43615f46df22ec3d36b4a53Al Viro	/* AV: what happens if we get called again before that gets through? */
998598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
9994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
1000598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
10014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
10074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
10144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
1015598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1017598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(m66592, ep->pipenum);
10194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_reg_sqclr(m66592, ep->pipenum);
10204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next,
10244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request, queue);
10254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (ep->busy) {
10264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ep->busy = 0;
10274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (list_empty(&ep->queue))
10284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				break;
10294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
10304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else if (!list_empty(&ep->queue))
10314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			pipe_start(m66592, ep->pipenum);
10324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1042ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda	u16 tmp;
1043ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda	int timeout = 3000;
10444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctrl->bRequestType & USB_RECIP_MASK) {
10464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_DEVICE:
1047ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		switch (le16_to_cpu(ctrl->wValue)) {
1048ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		case USB_DEVICE_TEST_MODE:
1049ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			control_end(m66592, 1);
1050ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			/* Wait for the completion of status stage */
1051ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			do {
1052ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda				tmp = m66592_read(m66592, M66592_INTSTS0) &
1053ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda								M66592_CTSQ;
1054ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda				udelay(1);
1055ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			} while (tmp != M66592_CS_IDST || timeout-- > 0);
1056ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda
1057ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			if (tmp == M66592_CS_IDST)
1058ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda				m66592_bset(m66592,
1059ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda					    le16_to_cpu(ctrl->wIndex >> 8),
1060ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda					    M66592_TESTMODE);
1061ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			break;
1062ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		default:
1063ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			pipe_stall(m66592, 0);
1064ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda			break;
1065ceaa0a6eeadfd2f53df121210d99a1f80ee7645eYoshihiro Shimoda		}
10664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_INTERFACE:
10684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case USB_RECIP_ENDPOINT: {
10714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
1072598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		u16 w_index = le16_to_cpu(ctrl->wIndex);
10734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1074598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
10754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, ep->pipenum);
10764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 1);
10784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
10794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
10814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(m66592, 0);
10824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
10834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
10844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
10854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/* if return value is true, call class driver's setup() */
10874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
10884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
10894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 *p = (u16 *)ctrl;
10904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long offset = M66592_USBREQ;
10914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i, ret = 0;
10924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* read fifo */
10944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
10954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < 4; i++)
10974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		p[i] = m66592_read(m66592, offset + i*2);
10984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
10994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* check request */
11004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
11014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		switch (ctrl->bRequest) {
11024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_GET_STATUS:
11034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			get_status(m66592, ctrl);
11044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_CLEAR_FEATURE:
11064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			clear_feature(m66592, ctrl);
11074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		case USB_REQ_SET_FEATURE:
11094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			set_feature(m66592, ctrl);
11104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		default:
11124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			ret = 1;
11134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			break;
11144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else
11164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = 1;
11174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
11184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_update_usb_speed(struct m66592 *m66592)
11214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 speed = get_usb_speed(m66592);
11234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (speed) {
11254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_HSMODE:
11264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_HIGH;
11274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_FSMODE:
11294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_FULL;
11304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
11324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->gadget.speed = USB_SPEED_UNKNOWN;
113300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("USB speed unknown\n");
11344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_device_state(struct m66592 *m66592)
11384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 dvsq;
11404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
11424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
11434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (dvsq == M66592_DS_DFLT) {	/* bus reset */
11454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->driver->disconnect(&m66592->gadget);
11464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
11494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
1150598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS)
1151598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			&& m66592->gadget.speed == USB_SPEED_UNKNOWN)
11524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_update_usb_speed(m66592);
11534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->old_dvsq = dvsq;
11554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void irq_control_stage(struct m66592 *m66592)
1158598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__releases(m66592->lock)
1159598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda__acquires(m66592->lock)
11604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct usb_ctrlrequest ctrl;
11624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 ctsq;
11634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
11654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
11664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	switch (ctsq) {
11684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_IDST: {
11694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep;
11704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_request *req;
11714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep = &m66592->ep[0];
11724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
11734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, 0);
11744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDDS:
11784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRDS:
11794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRND:
11804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (setup_packet(m66592, &ctrl)) {
1181598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_unlock(&m66592->lock);
11824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
11834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				pipe_stall(m66592, 0);
1184598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			spin_lock(&m66592->lock);
11854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
11864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_RDSS:
11884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	case M66592_CS_WRSS:
11894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		control_end(m66592, 0);
11904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	default:
119200274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
11934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		break;
11944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
11954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
11964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
11974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic irqreturn_t m66592_irq(int irq, void *_m66592)
11984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
11994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = _m66592;
12004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intsts0;
12014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 intenb0;
12024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdysts, nrdysts, bempsts;
12034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 brdyenb, nrdyenb, bempenb;
12044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 savepipe;
12054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 mask0;
12064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1207598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_lock(&m66592->lock);
1208598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
12094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intsts0 = m66592_read(m66592, M66592_INTSTS0);
12104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	intenb0 = m66592_read(m66592, M66592_INTENB0);
12114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12122c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip && !intsts0 && !intenb0) {
12138c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		/*
12148c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * When USB clock stops, it cannot read register. Even if a
12158c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * clock stops, the interrupt occurs. So this driver turn on
12168c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 * a clock by this timing and do re-reading of register.
12178c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		 */
12188c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		m66592_start_xclock(m66592);
12198c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intsts0 = m66592_read(m66592, M66592_INTSTS0);
12208c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda		intenb0 = m66592_read(m66592, M66592_INTENB0);
12218c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda	}
12228c73aff6d3b772e5f373d78bc34fd47b10b35fefYoshihiro Shimoda
12234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
12244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	mask0 = intsts0 & intenb0;
12264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (mask0) {
12274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdysts = m66592_read(m66592, M66592_BRDYSTS);
12284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdysts = m66592_read(m66592, M66592_NRDYSTS);
12294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempsts = m66592_read(m66592, M66592_BEMPSTS);
12304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		brdyenb = m66592_read(m66592, M66592_BRDYENB);
12314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		nrdyenb = m66592_read(m66592, M66592_NRDYENB);
12324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		bempenb = m66592_read(m66592, M66592_BEMPENB);
12334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (mask0 & M66592_VBINT) {
1235598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			m66592_write(m66592,  0xffff & ~M66592_VBINT,
1236598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					M66592_INTSTS0);
12374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_start_xclock(m66592);
12384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			/* start vbus sampling */
12404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
1241598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					& M66592_VBSTS;
12424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1245598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_DVSQ)
12484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_device_state(m66592);
12494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1250598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE)
1251598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (brdysts & brdyenb)) {
12524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_ready(m66592, brdysts, brdyenb);
12534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
1254598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE)
1255598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda				&& (bempsts & bempenb)) {
12564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_pipe_empty(m66592, bempsts, bempenb);
12574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
12584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (intsts0 & M66592_CTRT)
12604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			irq_control_stage(m66592);
12614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_write(m66592, savepipe, M66592_CFIFOSEL);
12644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1265598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	spin_unlock(&m66592->lock);
12664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return IRQ_HANDLED;
12674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
12684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_timer(unsigned long _m66592)
12704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
12714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = (struct m66592 *)_m66592;
12724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
12734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	u16 tmp;
12744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
12754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
12764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	tmp = m66592_read(m66592, M66592_SYSCFG);
12774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!(tmp & M66592_RCKE)) {
12784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
12794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		udelay(10);
12804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
12814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
12824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->scount > 0) {
12834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
12844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (tmp == m66592->old_vbus) {
12854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount--;
12864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			if (m66592->scount == 0) {
12874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				if (tmp == M66592_VBSTS)
12884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_connect(m66592);
12894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				else
12904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					m66592_usb_disconnect(m66592);
12914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			} else {
12924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda				mod_timer(&m66592->timer,
1293598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
12944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			}
12954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		} else {
12964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->scount = M66592_MAX_SAMPLING;
12974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592->old_vbus = tmp;
12984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			mod_timer(&m66592->timer,
1299598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					jiffies + msecs_to_jiffies(50));
13004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
13014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
13034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
13064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_enable(struct usb_ep *_ep,
13074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			 const struct usb_endpoint_descriptor *desc)
13084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return alloc_pipe_config(ep, desc);
13134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_disable(struct usb_ep *_ep)
13164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	BUG_ON(!ep);
13234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	while (!list_empty(&ep->queue)) {
13254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		req = list_entry(ep->queue.next, struct m66592_request, queue);
13264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_lock_irqsave(&ep->m66592->lock, flags);
13274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
13284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		spin_unlock_irqrestore(&ep->m66592->lock, flags);
13294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	pipe_irq_disable(ep->m66592, ep->pipenum);
13324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return free_pipe_config(ep);
13334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
13364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda						gfp_t gfp_flags)
13374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = kzalloc(sizeof(struct m66592_request), gfp_flags);
13414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!req)
13424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return NULL;
13434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&req->queue);
13454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return &req->req;
13474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
13504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(req);
13554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
13584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			gfp_t gfp_flags)
13594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int request = 0;
13644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
13674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
13694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ESHUTDOWN;
13704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
13724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue))
13744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		request = 1;
13754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13764cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	list_add_tail(&req->queue, &ep->queue);
13774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.actual = 0;
13784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req->req.status = -EINPROGRESS;
13794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1380a9475226977917afd5a85621f8a3d7f380a9da31David Brownell	if (ep->desc == NULL)	/* control */
13814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		start_ep0(ep, req);
13824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	else {
13834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (request && !ep->busy)
13844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			start_packet(ep, req);
13854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
13864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
13884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
13904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
13914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
13934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
13944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
13954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
13964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
13974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
13984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
13994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = container_of(_req, struct m66592_request, req);
14004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue))
14034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		transfer_complete(ep, req, -ECONNRESET);
14044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
14074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_set_halt(struct usb_ep *_ep, int value)
14104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_request *req;
14134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
14154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	req = list_entry(ep->queue.next, struct m66592_request, queue);
14184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!list_empty(&ep->queue)) {
14214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -EAGAIN;
14224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto out;
14234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (value) {
14254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 1;
14264cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stall(ep->m66592, ep->pipenum);
14274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	} else {
14284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->busy = 0;
14294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaout:
14334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
14354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14374cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void m66592_fifo_flush(struct usb_ep *_ep)
14384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592_ep *ep;
14404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
14414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	ep = container_of(_ep, struct m66592_ep, ep);
14434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&ep->m66592->lock, flags);
14444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (list_empty(&ep->queue) && !ep->busy) {
14454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		pipe_stop(ep->m66592, ep->pipenum);
14464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
14474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&ep->m66592->lock, flags);
14494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
14504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_ep_ops m66592_ep_ops = {
14524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.enable		= m66592_enable,
14534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.disable	= m66592_disable,
14544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.alloc_request	= m66592_alloc_request,
14564cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.free_request	= m66592_free_request,
14574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.queue		= m66592_queue,
14594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.dequeue	= m66592_dequeue,
14604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.set_halt	= m66592_set_halt,
14624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.fifo_flush	= m66592_fifo_flush,
14634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
14644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
14664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct m66592 *the_controller;
14674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14680f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorstatic int m66592_start(struct usb_gadget_driver *driver,
1469b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König		int (*bind)(struct usb_gadget *))
14704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
14714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
14724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int retval;
14734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1474598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (!driver
14757177aed44f515d949f587170e0e177ce17e74793Michal Nazarewicz			|| driver->max_speed < USB_SPEED_HIGH
1476b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König			|| !bind
1477598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			|| !driver->setup)
14784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EINVAL;
14794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!m66592)
14804cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -ENODEV;
14814cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->driver)
14824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		return -EBUSY;
14834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* hook up the driver */
14854cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->driver.bus = NULL;
14864cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = driver;
14874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = &driver->driver;
14884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
14894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	retval = device_add(&m66592->gadget.dev);
14904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
149100274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("device_add error (%d)\n", retval);
14924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
14934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
14944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1495b0fca50f5a94a268ed02cfddf44448051ed9343fUwe Kleine-König	retval = bind(&m66592->gadget);
14964cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (retval) {
149700274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("bind to driver error (%d)\n", retval);
14984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		device_del(&m66592->gadget.dev);
14994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto error;
15004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
15034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
15044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_start_xclock(m66592);
15054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		/* start vbus sampling */
15064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->old_vbus = m66592_read(m66592,
15074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda					 M66592_INTSTS0) & M66592_VBSTS;
15084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592->scount = M66592_MAX_SAMPLING;
1509598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50));
15104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
15114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaerror:
15154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.driver = NULL;
15174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15184cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return retval;
15194cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15210f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorstatic int m66592_stop(struct usb_gadget_driver *driver)
15224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = the_controller;
15244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	unsigned long flags;
15254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1526598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	if (driver != m66592->driver || !driver->unbind)
1527598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda		return -EINVAL;
1528598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
15294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
15304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
15314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		m66592_usb_disconnect(m66592);
15324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
15334cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15344cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
15354cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15364cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	driver->unbind(&m66592->gadget);
1537eb0be47dbbdca133b1b94adc564297f25176b3abPatrik Sevallius	m66592->gadget.dev.driver = NULL;
15384cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
15404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	disable_controller(m66592);
15414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_del(&m66592->gadget.dev);
15434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->driver = NULL;
15444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
15484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int m66592_get_frame(struct usb_gadget *_gadget)
15494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = gadget_to_m66592(_gadget);
15514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
15524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15547eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimodastatic int m66592_pullup(struct usb_gadget *gadget, int is_on)
15557eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda{
15567eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	struct m66592 *m66592 = gadget_to_m66592(gadget);
15577eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	unsigned long flags;
15587eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda
15597eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	spin_lock_irqsave(&m66592->lock, flags);
15607eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	if (is_on)
15617eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda		m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
15627eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	else
15637eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda		m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
15647eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	spin_unlock_irqrestore(&m66592->lock, flags);
15657eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda
15667eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	return 0;
15677eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda}
15687eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda
15694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct usb_gadget_ops m66592_gadget_ops = {
15704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.get_frame		= m66592_get_frame,
15710f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	.start			= m66592_start,
15720f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	.stop			= m66592_stop,
15737eff1d83a3b846d16a4cd706d06b5827a07c08a3Yoshihiro Shimoda	.pullup			= m66592_pullup,
15744cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
15754cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1576598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic int __exit m66592_remove(struct platform_device *pdev)
15774cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
15784cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);
15794cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
15800f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	usb_del_gadget_udc(&m66592->gadget);
15810f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
15824cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	del_timer_sync(&m66592->timer);
15834cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	iounmap(m66592->reg);
15844cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	free_irq(platform_get_irq(pdev, 0), m66592);
1585598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
15862c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
15872c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
15882c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_disable(m66592->clk);
15892c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_put(m66592->clk);
15902c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
1591af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
15924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	kfree(m66592);
15934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
15944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
15954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1596598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodastatic void nop_completion(struct usb_ep *ep, struct usb_request *r)
1597598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda{
1598598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda}
1599598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda
16004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_probe(struct platform_device *pdev)
16014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
16022c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	struct resource *res, *ires;
16034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	void __iomem *reg = NULL;
16044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	struct m66592 *m66592 = NULL;
16052c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
1606af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm	char clk_name[8];
1607af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
16084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int ret = 0;
16094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	int i;
16104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16110a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
16124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (!res) {
16134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
16140a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm		pr_err("platform_get_resource error.\n");
16154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16182c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
16192c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (!ires) {
16204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENODEV;
16212c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		dev_err(&pdev->dev,
16222c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			"platform_get_resource IORESOURCE_IRQ error.\n");
16234cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16244cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16254cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16260a2e5b9b8a3d205b565dec18d6fe39ef1aed75ccMagnus Damm	reg = ioremap(res->start, resource_size(res));
16274cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg == NULL) {
16284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ret = -ENOMEM;
162900274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("ioremap error.\n");
16304cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16314cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16324cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16332c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (pdev->dev.platform_data == NULL) {
16342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		dev_err(&pdev->dev, "no platform data\n");
16352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		ret = -ENODEV;
16362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		goto clean_up;
16372c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
16382c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
16394cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	/* initialize ucd */
16404cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
16414cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592 == NULL) {
16427c81aafaf059b81ead2330bc13db78269ef62612Julia Lawall		ret = -ENOMEM;
164300274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("kzalloc error\n");
16444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16472c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592->pdata = pdev->dev.platform_data;
16482c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK;
16492c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm
16504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	spin_lock_init(&m66592->lock);
16514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	dev_set_drvdata(&pdev->dev, m66592);
16524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ops = &m66592_gadget_ops;
16544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	device_initialize(&m66592->gadget.dev);
1655836e4b14b41d19d17341a2dd2c49af8dd54e3aacPaul Mundt	dev_set_name(&m66592->gadget.dev, "gadget");
1656d327ab5b6d660d6fe22b073b743fde1668e593bbMichal Nazarewicz	m66592->gadget.max_speed = USB_SPEED_HIGH;
16574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.parent = &pdev->dev;
16584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
16594cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.dev.release = pdev->dev.release;
16604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.name = udc_name;
16614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_timer(&m66592->timer);
16634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.function = m66592_timer;
16644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->timer.data = (unsigned long)m66592;
16654cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->reg = reg;
16664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
1667b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang	ret = request_irq(ires->start, m66592_irq, IRQF_SHARED,
1668598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda			udc_name, m66592);
16694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (ret < 0) {
167000274921a052d3232d9f00856387fb269ac0af11David Brownell		pr_err("request_irq error (%d)\n", ret);
16714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		goto clean_up;
16724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
16734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16742c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
16752c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
16762c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id);
16772c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		m66592->clk = clk_get(&pdev->dev, clk_name);
16782c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		if (IS_ERR(m66592->clk)) {
16792c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
16802c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm				clk_name);
16812c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			ret = PTR_ERR(m66592->clk);
16822c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm			goto clean_up2;
16832c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		}
16842c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_enable(m66592->clk);
1685af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm	}
1686af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm#endif
16874cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep_list);
16884cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->gadget.ep0 = &m66592->ep[0].ep;
16894cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
16904cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
16914cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		struct m66592_ep *ep = &m66592->ep[i];
16924cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
16934cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (i != 0) {
16944cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
16954cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			list_add_tail(&m66592->ep[i].ep.ep_list,
1696598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda					&m66592->gadget.ep_list);
16974cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		}
16984cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->m66592 = m66592;
16994cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		INIT_LIST_HEAD(&ep->queue);
17004cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.name = m66592_ep_name[i];
17014cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.ops = &m66592_ep_ops;
17024cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		ep->ep.maxpacket = 512;
17034cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
17044cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].ep.maxpacket = 64;
17054cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipenum = 0;
17064cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoaddr = M66592_CFIFO;
17074cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifosel = M66592_CFIFOSEL;
17084cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifoctr = M66592_CFIFOCTR;
17094cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].fifotrn = 0;
17104cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep[0].pipectr = get_pipectr_addr(0);
17114cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->pipenum2ep[0] = &m66592->ep[0];
17124cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->epaddr2ep[0] = &m66592->ep[0];
17134cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17144cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	the_controller = m66592;
17154cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17164cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
17174cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592->ep0_req == NULL)
1718af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Damm		goto clean_up3;
1719598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	m66592->ep0_req->complete = nop_completion;
17204cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17214cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	init_controller(m66592);
17224cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17230f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
17240f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	if (ret)
17250f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior		goto err_add_udc;
17260f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
1727598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
17284cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return 0;
17294cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17300f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewiorerr_add_udc:
17310f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
17320f91349b89f37dfad7b77f7829a105b6a0f526ecSebastian Andrzej Siewior
1733af5be79a7f8d7067588dc2863d37f7cd22e5f2deMagnus Dammclean_up3:
17342c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm#ifdef CONFIG_HAVE_CLK
17352c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	if (m66592->pdata->on_chip) {
17362c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_disable(m66592->clk);
17372c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm		clk_put(m66592->clk);
17382c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	}
1739598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimodaclean_up2:
1740d6435102d4ca3b5655c0105abe924abec17ffeb8Paul Mundt#endif
17412c59b0b70b9d5d61c726f179724660c4c2423f31Magnus Damm	free_irq(ires->start, m66592);
17424cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodaclean_up:
17434cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (m66592) {
17444cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		if (m66592->ep0_req)
17454cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda			m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
17464cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		kfree(m66592);
17474cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	}
17484cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	if (reg)
17494cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		iounmap(reg);
17504cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17514cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	return ret;
17524cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17534cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17544cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda/*-------------------------------------------------------------------------*/
17554cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic struct platform_driver m66592_driver = {
1756598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	.remove =	__exit_p(m66592_remove),
17574cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	.driver		= {
17584cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda		.name =	(char *) udc_name,
1759f34c32f13ce8c539f3f582562358e39a86b00e83Kay Sievers		.owner	= THIS_MODULE,
17604cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	},
17614cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda};
17624cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17634cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic int __init m66592_udc_init(void)
17644cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
1765598f22e11bef8171f2244128bf0341da38fe8a23Yoshihiro Shimoda	return platform_driver_probe(&m66592_driver, m66592_probe);
17664cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17674cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_init(m66592_udc_init);
17684cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda
17694cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodastatic void __exit m66592_udc_cleanup(void)
17704cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda{
17714cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda	platform_driver_unregister(&m66592_driver);
17724cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimoda}
17734cf2503c6801a69fee25030475eceeefb36d1b56Yoshihiro Shimodamodule_exit(m66592_udc_cleanup);
1774