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