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