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