2011-04-05 11:40:54 +09:00
/*
* Renesas USB driver
*
* Copyright ( C ) 2011 Renesas Solutions Corp .
* Kuninori Morimoto < kuninori . morimoto . gx @ renesas . com >
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*
*/
2011-11-24 17:28:35 -08:00
# include <linux/delay.h>
2011-08-03 21:41:26 -07:00
# include <linux/dma-mapping.h>
2011-04-05 11:40:54 +09:00
# include <linux/io.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/usb/ch9.h>
# include <linux/usb/gadget.h>
# include "common.h"
/*
* struct
*/
struct usbhsg_request {
struct usb_request req ;
2011-06-06 14:18:07 +09:00
struct usbhs_pkt pkt ;
2011-04-05 11:40:54 +09:00
} ;
# define EP_NAME_SIZE 8
struct usbhsg_gpriv ;
struct usbhsg_uep {
struct usb_ep ep ;
struct usbhs_pipe * pipe ;
char ep_name [ EP_NAME_SIZE ] ;
struct usbhsg_gpriv * gpriv ;
} ;
struct usbhsg_gpriv {
struct usb_gadget gadget ;
struct usbhs_mod mod ;
struct usbhsg_uep * uep ;
int uep_size ;
struct usb_gadget_driver * driver ;
u32 status ;
# define USBHSG_STATUS_STARTED (1 << 0)
# define USBHSG_STATUS_REGISTERD (1 << 1)
# define USBHSG_STATUS_WEDGE (1 << 2)
2012-03-16 13:10:15 +09:00
# define USBHSG_STATUS_SELF_POWERED (1 << 3)
2011-04-05 11:40:54 +09:00
} ;
struct usbhsg_recip_handle {
char * name ;
int ( * device ) ( struct usbhs_priv * priv , struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl ) ;
int ( * interface ) ( struct usbhs_priv * priv , struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl ) ;
int ( * endpoint ) ( struct usbhs_priv * priv , struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl ) ;
} ;
/*
* macro
*/
# define usbhsg_priv_to_gpriv(priv) \
container_of ( \
usbhs_mod_get ( priv , USBHS_GADGET ) , \
struct usbhsg_gpriv , mod )
# define __usbhsg_for_each_uep(start, pos, g, i) \
2013-07-11 22:32:31 -07:00
for ( ( i ) = start ; \
( ( i ) < ( g ) - > uep_size ) & & ( ( pos ) = ( g ) - > uep + ( i ) ) ; \
( i ) + + )
2011-04-05 11:40:54 +09:00
# define usbhsg_for_each_uep(pos, gpriv, i) \
__usbhsg_for_each_uep ( 1 , pos , gpriv , i )
# define usbhsg_for_each_uep_with_dcp(pos, gpriv, i) \
__usbhsg_for_each_uep ( 0 , pos , gpriv , i )
# define usbhsg_gadget_to_gpriv(g)\
container_of ( g , struct usbhsg_gpriv , gadget )
# define usbhsg_req_to_ureq(r)\
container_of ( r , struct usbhsg_request , req )
# define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep)
# define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv)
# define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv)
# define usbhsg_gpriv_to_dcp(gp) ((gp)->uep)
# define usbhsg_gpriv_to_nth_uep(gp, i) ((gp)->uep + i)
# define usbhsg_uep_to_gpriv(u) ((u)->gpriv)
# define usbhsg_uep_to_pipe(u) ((u)->pipe)
# define usbhsg_pipe_to_uep(p) ((p)->mod_private)
# define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv))
2011-06-06 14:18:07 +09:00
# define usbhsg_ureq_to_pkt(u) (&(u)->pkt)
# define usbhsg_pkt_to_ureq(i) \
container_of ( i , struct usbhsg_request , pkt )
2011-04-05 11:40:54 +09:00
# define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN)
/* status */
# define usbhsg_status_init(gp) do {(gp)->status = 0; } while (0)
# define usbhsg_status_set(gp, b) (gp->status |= b)
# define usbhsg_status_clr(gp, b) (gp->status &= ~b)
# define usbhsg_status_has(gp, b) (gp->status & b)
/*
2011-07-07 00:23:24 -07:00
* queue push / pop
2011-04-05 11:40:54 +09:00
*/
static void usbhsg_queue_pop ( struct usbhsg_uep * uep ,
struct usbhsg_request * ureq ,
int status )
{
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
dev_dbg ( dev , " pipe %d : queue pop \n " , usbhs_pipe_number ( pipe ) ) ;
ureq - > req . status = status ;
ureq - > req . complete ( & uep - > ep , & ureq - > req ) ;
}
2011-10-10 22:03:39 -07:00
static void usbhsg_queue_done ( struct usbhs_priv * priv , struct usbhs_pkt * pkt )
2011-04-05 11:40:54 +09:00
{
2011-06-06 14:18:07 +09:00
struct usbhs_pipe * pipe = pkt - > pipe ;
struct usbhsg_uep * uep = usbhsg_pipe_to_uep ( pipe ) ;
struct usbhsg_request * ureq = usbhsg_pkt_to_ureq ( pkt ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:23 +09:00
ureq - > req . actual = pkt - > actual ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:23 +09:00
usbhsg_queue_pop ( uep , ureq , 0 ) ;
2011-06-06 14:18:07 +09:00
}
2011-10-10 22:04:41 -07:00
static void usbhsg_queue_push ( struct usbhsg_uep * uep ,
struct usbhsg_request * ureq )
{
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
struct usbhs_pkt * pkt = usbhsg_ureq_to_pkt ( ureq ) ;
struct usb_request * req = & ureq - > req ;
req - > actual = 0 ;
req - > status = - EINPROGRESS ;
usbhs_pkt_push ( pipe , pkt , usbhsg_queue_done ,
2011-12-08 18:28:54 -08:00
req - > buf , req - > length , req - > zero , - 1 ) ;
2011-10-10 22:04:53 -07:00
usbhs_pkt_start ( pipe ) ;
2011-10-10 22:04:41 -07:00
dev_dbg ( dev , " pipe %d : queue push (%d) \n " ,
usbhs_pipe_number ( pipe ) ,
req - > length ) ;
}
2011-07-07 00:23:24 -07:00
/*
* dma map / unmap
*/
2011-12-19 11:57:16 +02:00
static int usbhsg_dma_map_ctrl ( struct usbhs_pkt * pkt , int map )
2011-06-06 14:19:03 +09:00
{
struct usbhsg_request * ureq = usbhsg_pkt_to_ureq ( pkt ) ;
struct usb_request * req = & ureq - > req ;
struct usbhs_pipe * pipe = pkt - > pipe ;
struct usbhsg_uep * uep = usbhsg_pipe_to_uep ( pipe ) ;
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
enum dma_data_direction dir ;
2011-12-19 11:57:16 +02:00
int ret = 0 ;
2011-06-06 14:19:03 +09:00
2011-12-19 11:57:16 +02:00
dir = usbhs_pipe_is_dir_host ( pipe ) ;
2011-06-06 14:19:03 +09:00
2011-12-19 11:57:16 +02:00
if ( map ) {
/* it can not use scatter/gather */
WARN_ON ( req - > num_sgs ) ;
ret = usb_gadget_map_request ( & gpriv - > gadget , req , dir ) ;
if ( ret < 0 )
return ret ;
pkt - > dma = req - > dma ;
} else {
usb_gadget_unmap_request ( & gpriv - > gadget , req , dir ) ;
}
return ret ;
2011-06-06 14:19:03 +09:00
}
2011-04-05 11:40:54 +09:00
/*
* USB_TYPE_STANDARD / clear feature functions
*/
static int usbhsg_recip_handler_std_control_done ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
struct usbhsg_uep * dcp = usbhsg_gpriv_to_dcp ( gpriv ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( dcp ) ;
usbhs_dcp_control_transfer_done ( pipe ) ;
return 0 ;
}
static int usbhsg_recip_handler_std_clear_endpoint ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
if ( ! usbhsg_status_has ( gpriv , USBHSG_STATUS_WEDGE ) ) {
2011-06-06 14:18:03 +09:00
usbhs_pipe_disable ( pipe ) ;
2011-10-10 22:05:30 -07:00
usbhs_pipe_sequence_data0 ( pipe ) ;
2011-06-06 14:18:03 +09:00
usbhs_pipe_enable ( pipe ) ;
2011-04-05 11:40:54 +09:00
}
usbhsg_recip_handler_std_control_done ( priv , uep , ctrl ) ;
2011-11-24 17:28:17 -08:00
usbhs_pkt_start ( pipe ) ;
2011-04-05 11:40:54 +09:00
return 0 ;
}
2013-03-31 18:34:43 -07:00
static struct usbhsg_recip_handle req_clear_feature = {
2011-04-05 11:40:54 +09:00
. name = " clear feature " ,
. device = usbhsg_recip_handler_std_control_done ,
. interface = usbhsg_recip_handler_std_control_done ,
. endpoint = usbhsg_recip_handler_std_clear_endpoint ,
} ;
2011-11-24 17:27:50 -08:00
/*
* USB_TYPE_STANDARD / set feature functions
*/
2011-11-24 17:28:35 -08:00
static int usbhsg_recip_handler_std_set_device ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
switch ( le16_to_cpu ( ctrl - > wValue ) ) {
case USB_DEVICE_TEST_MODE :
usbhsg_recip_handler_std_control_done ( priv , uep , ctrl ) ;
udelay ( 100 ) ;
usbhs_sys_set_test_mode ( priv , le16_to_cpu ( ctrl - > wIndex > > 8 ) ) ;
break ;
default :
usbhsg_recip_handler_std_control_done ( priv , uep , ctrl ) ;
break ;
}
return 0 ;
}
2011-11-24 17:27:50 -08:00
static int usbhsg_recip_handler_std_set_endpoint ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
usbhs_pipe_stall ( pipe ) ;
usbhsg_recip_handler_std_control_done ( priv , uep , ctrl ) ;
return 0 ;
}
2013-03-31 18:34:43 -07:00
static struct usbhsg_recip_handle req_set_feature = {
2011-11-24 17:27:50 -08:00
. name = " set feature " ,
2011-11-24 17:28:35 -08:00
. device = usbhsg_recip_handler_std_set_device ,
2011-11-24 17:27:50 -08:00
. interface = usbhsg_recip_handler_std_control_done ,
. endpoint = usbhsg_recip_handler_std_set_endpoint ,
} ;
2011-11-24 17:28:04 -08:00
/*
* USB_TYPE_STANDARD / get status functions
*/
static void __usbhsg_recip_send_complete ( struct usb_ep * ep ,
struct usb_request * req )
{
struct usbhsg_request * ureq = usbhsg_req_to_ureq ( req ) ;
/* free allocated recip-buffer/usb_request */
kfree ( ureq - > pkt . buf ) ;
usb_ep_free_request ( ep , req ) ;
}
static void __usbhsg_recip_send_status ( struct usbhsg_gpriv * gpriv ,
unsigned short status )
{
struct usbhsg_uep * dcp = usbhsg_gpriv_to_dcp ( gpriv ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( dcp ) ;
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
struct usb_request * req ;
unsigned short * buf ;
/* alloc new usb_request for recip */
req = usb_ep_alloc_request ( & dcp - > ep , GFP_ATOMIC ) ;
if ( ! req ) {
dev_err ( dev , " recip request allocation fail \n " ) ;
return ;
}
/* alloc recip data buffer */
buf = kmalloc ( sizeof ( * buf ) , GFP_ATOMIC ) ;
if ( ! buf ) {
usb_ep_free_request ( & dcp - > ep , req ) ;
dev_err ( dev , " recip data allocation fail \n " ) ;
return ;
}
/* recip data is status */
* buf = cpu_to_le16 ( status ) ;
/* allocated usb_request/buffer will be freed */
req - > complete = __usbhsg_recip_send_complete ;
req - > buf = buf ;
req - > length = sizeof ( * buf ) ;
req - > zero = 0 ;
/* push packet */
pipe - > handler = & usbhs_fifo_pio_push_handler ;
usbhsg_queue_push ( dcp , usbhsg_req_to_ureq ( req ) ) ;
}
static int usbhsg_recip_handler_std_get_device ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
2012-03-16 13:10:15 +09:00
unsigned short status = 0 ;
if ( usbhsg_status_has ( gpriv , USBHSG_STATUS_SELF_POWERED ) )
status = 1 < < USB_DEVICE_SELF_POWERED ;
2011-11-24 17:28:04 -08:00
__usbhsg_recip_send_status ( gpriv , status ) ;
return 0 ;
}
static int usbhsg_recip_handler_std_get_interface ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
unsigned short status = 0 ;
__usbhsg_recip_send_status ( gpriv , status ) ;
return 0 ;
}
static int usbhsg_recip_handler_std_get_endpoint ( struct usbhs_priv * priv ,
struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl )
{
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
unsigned short status = 0 ;
if ( usbhs_pipe_is_stall ( pipe ) )
status = 1 < < USB_ENDPOINT_HALT ;
__usbhsg_recip_send_status ( gpriv , status ) ;
return 0 ;
}
2013-03-31 18:34:43 -07:00
static struct usbhsg_recip_handle req_get_status = {
2011-11-24 17:28:04 -08:00
. name = " get status " ,
. device = usbhsg_recip_handler_std_get_device ,
. interface = usbhsg_recip_handler_std_get_interface ,
. endpoint = usbhsg_recip_handler_std_get_endpoint ,
} ;
2011-04-05 11:40:54 +09:00
/*
* USB_TYPE handler
*/
static int usbhsg_recip_run_handle ( struct usbhs_priv * priv ,
struct usbhsg_recip_handle * handler ,
struct usb_ctrlrequest * ctrl )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
struct usbhsg_uep * uep ;
2011-06-06 14:18:54 +09:00
struct usbhs_pipe * pipe ;
2011-04-05 11:40:54 +09:00
int recip = ctrl - > bRequestType & USB_RECIP_MASK ;
int nth = le16_to_cpu ( ctrl - > wIndex ) & USB_ENDPOINT_NUMBER_MASK ;
2012-01-16 22:42:10 +01:00
int ret = 0 ;
2011-04-05 11:40:54 +09:00
int ( * func ) ( struct usbhs_priv * priv , struct usbhsg_uep * uep ,
struct usb_ctrlrequest * ctrl ) ;
char * msg ;
uep = usbhsg_gpriv_to_nth_uep ( gpriv , nth ) ;
2011-06-06 14:18:54 +09:00
pipe = usbhsg_uep_to_pipe ( uep ) ;
if ( ! pipe ) {
2011-04-21 14:10:12 +09:00
dev_err ( dev , " wrong recip request \n " ) ;
2011-11-24 17:28:17 -08:00
return - EINVAL ;
2011-04-21 14:10:12 +09:00
}
2011-04-05 11:40:54 +09:00
switch ( recip ) {
case USB_RECIP_DEVICE :
msg = " DEVICE " ;
func = handler - > device ;
break ;
case USB_RECIP_INTERFACE :
msg = " INTERFACE " ;
func = handler - > interface ;
break ;
case USB_RECIP_ENDPOINT :
msg = " ENDPOINT " ;
func = handler - > endpoint ;
break ;
default :
dev_warn ( dev , " unsupported RECIP(%d) \n " , recip ) ;
func = NULL ;
ret = - EINVAL ;
}
if ( func ) {
dev_dbg ( dev , " %s (pipe %d :%s) \n " , handler - > name , nth , msg ) ;
ret = func ( priv , uep , ctrl ) ;
}
return ret ;
}
/*
* irq functions
*
* it will be called from usbhs_interrupt
*/
static int usbhsg_irq_dev_state ( struct usbhs_priv * priv ,
struct usbhs_irq_state * irq_state )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
2011-10-10 22:01:51 -07:00
gpriv - > gadget . speed = usbhs_bus_get_speed ( priv ) ;
2011-04-05 11:40:54 +09:00
dev_dbg ( dev , " state = %x : speed : %d \n " ,
usbhs_status_get_device_state ( irq_state ) ,
gpriv - > gadget . speed ) ;
return 0 ;
}
static int usbhsg_irq_ctrl_stage ( struct usbhs_priv * priv ,
struct usbhs_irq_state * irq_state )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
struct usbhsg_uep * dcp = usbhsg_gpriv_to_dcp ( gpriv ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( dcp ) ;
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
struct usb_ctrlrequest ctrl ;
struct usbhsg_recip_handle * recip_handler = NULL ;
int stage = usbhs_status_get_ctrl_stage ( irq_state ) ;
int ret = 0 ;
dev_dbg ( dev , " stage = %d \n " , stage ) ;
/*
* see Manual
*
* " Operation "
* - " Interrupt Function "
* - " Control Transfer Stage Transition Interrupt "
* - Fig . " Control Transfer Stage Transitions "
*/
switch ( stage ) {
case READ_DATA_STAGE :
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_fifo_pio_push_handler ;
2011-04-05 11:40:54 +09:00
break ;
case WRITE_DATA_STAGE :
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_fifo_pio_pop_handler ;
2011-04-05 11:40:54 +09:00
break ;
case NODATA_STATUS_STAGE :
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_ctrl_stage_end_handler ;
2011-04-05 11:40:54 +09:00
break ;
default :
return ret ;
}
/*
* get usb request
*/
usbhs_usbreq_get_val ( priv , & ctrl ) ;
switch ( ctrl . bRequestType & USB_TYPE_MASK ) {
case USB_TYPE_STANDARD :
switch ( ctrl . bRequest ) {
case USB_REQ_CLEAR_FEATURE :
recip_handler = & req_clear_feature ;
break ;
2011-11-24 17:27:50 -08:00
case USB_REQ_SET_FEATURE :
recip_handler = & req_set_feature ;
break ;
2011-11-24 17:28:04 -08:00
case USB_REQ_GET_STATUS :
recip_handler = & req_get_status ;
break ;
2011-04-05 11:40:54 +09:00
}
}
/*
* setup stage / run recip
*/
if ( recip_handler )
ret = usbhsg_recip_run_handle ( priv , recip_handler , & ctrl ) ;
else
ret = gpriv - > driver - > setup ( & gpriv - > gadget , & ctrl ) ;
if ( ret < 0 )
2011-06-06 14:18:03 +09:00
usbhs_pipe_stall ( pipe ) ;
2011-04-05 11:40:54 +09:00
return ret ;
}
/*
*
* usb_dcp_ops
*
*/
static int usbhsg_pipe_disable ( struct usbhsg_uep * uep )
{
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
2011-06-06 14:18:33 +09:00
struct usbhs_pkt * pkt ;
2011-04-05 11:40:54 +09:00
while ( 1 ) {
2011-06-06 14:18:38 +09:00
pkt = usbhs_pkt_pop ( pipe , NULL ) ;
2011-06-06 14:18:33 +09:00
if ( ! pkt )
2011-04-05 11:40:54 +09:00
break ;
2011-11-24 17:28:26 -08:00
usbhsg_queue_pop ( uep , usbhsg_pkt_to_ureq ( pkt ) , - ECONNRESET ) ;
2011-04-05 11:40:54 +09:00
}
2011-11-24 17:28:26 -08:00
usbhs_pipe_disable ( pipe ) ;
2011-04-05 11:40:54 +09:00
return 0 ;
}
/*
*
* usb_ep_ops
*
*/
static int usbhsg_ep_enable ( struct usb_ep * ep ,
const struct usb_endpoint_descriptor * desc )
{
struct usbhsg_uep * uep = usbhsg_ep_to_uep ( ep ) ;
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
struct usbhs_pipe * pipe ;
int ret = - EIO ;
2011-04-26 09:21:35 +09:00
/*
* if it already have pipe ,
* nothing to do
*/
2011-06-09 16:48:25 +09:00
if ( uep - > pipe ) {
usbhs_pipe_clear ( uep - > pipe ) ;
2011-10-10 22:05:30 -07:00
usbhs_pipe_sequence_data0 ( uep - > pipe ) ;
2011-04-26 09:21:35 +09:00
return 0 ;
2011-06-09 16:48:25 +09:00
}
2011-04-26 09:21:35 +09:00
2011-10-10 21:59:46 -07:00
pipe = usbhs_pipe_malloc ( priv ,
usb_endpoint_type ( desc ) ,
usb_endpoint_dir_in ( desc ) ) ;
2011-04-05 11:40:54 +09:00
if ( pipe ) {
uep - > pipe = pipe ;
pipe - > mod_private = uep ;
2011-10-10 21:59:46 -07:00
/* set epnum / maxp */
2011-10-10 22:04:00 -07:00
usbhs_pipe_config_update ( pipe , 0 ,
2011-10-10 21:59:46 -07:00
usb_endpoint_num ( desc ) ,
usb_endpoint_maxp ( desc ) ) ;
2011-07-07 00:23:24 -07:00
/*
* usbhs_fifo_dma_push / pop_handler try to
* use dmaengine if possible .
* It will use pio handler if impossible .
*/
2011-04-05 11:40:54 +09:00
if ( usb_endpoint_dir_in ( desc ) )
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_fifo_dma_push_handler ;
2011-04-05 11:40:54 +09:00
else
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_fifo_dma_pop_handler ;
2011-04-05 11:40:54 +09:00
ret = 0 ;
}
2011-04-21 14:10:08 +09:00
2011-04-05 11:40:54 +09:00
return ret ;
}
static int usbhsg_ep_disable ( struct usb_ep * ep )
{
struct usbhsg_uep * uep = usbhsg_ep_to_uep ( ep ) ;
2012-12-10 22:44:07 -08:00
usbhsg_pipe_disable ( uep ) ;
uep - > pipe - > mod_private = NULL ;
uep - > pipe = NULL ;
return 0 ;
2011-04-05 11:40:54 +09:00
}
static struct usb_request * usbhsg_ep_alloc_request ( struct usb_ep * ep ,
gfp_t gfp_flags )
{
struct usbhsg_request * ureq ;
ureq = kzalloc ( sizeof * ureq , gfp_flags ) ;
if ( ! ureq )
return NULL ;
2011-06-06 14:18:16 +09:00
usbhs_pkt_init ( usbhsg_ureq_to_pkt ( ureq ) ) ;
2011-04-05 11:40:54 +09:00
return & ureq - > req ;
}
static void usbhsg_ep_free_request ( struct usb_ep * ep ,
struct usb_request * req )
{
struct usbhsg_request * ureq = usbhsg_req_to_ureq ( req ) ;
2011-06-06 14:18:16 +09:00
WARN_ON ( ! list_empty ( & ureq - > pkt . node ) ) ;
2011-04-05 11:40:54 +09:00
kfree ( ureq ) ;
}
static int usbhsg_ep_queue ( struct usb_ep * ep , struct usb_request * req ,
gfp_t gfp_flags )
{
struct usbhsg_uep * uep = usbhsg_ep_to_uep ( ep ) ;
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
struct usbhsg_request * ureq = usbhsg_req_to_ureq ( req ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
/* param check */
if ( usbhsg_is_not_connected ( gpriv ) | |
unlikely ( ! gpriv - > driver ) | |
unlikely ( ! pipe ) )
2011-06-06 14:18:38 +09:00
return - ESHUTDOWN ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
usbhsg_queue_push ( uep , ureq ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
return 0 ;
2011-04-05 11:40:54 +09:00
}
static int usbhsg_ep_dequeue ( struct usb_ep * ep , struct usb_request * req )
{
struct usbhsg_uep * uep = usbhsg_ep_to_uep ( ep ) ;
struct usbhsg_request * ureq = usbhsg_req_to_ureq ( req ) ;
2011-06-06 14:18:38 +09:00
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
usbhs_pkt_pop ( pipe , usbhsg_ureq_to_pkt ( ureq ) ) ;
2011-04-05 11:40:54 +09:00
usbhsg_queue_pop ( uep , ureq , - ECONNRESET ) ;
return 0 ;
}
static int __usbhsg_ep_set_halt_wedge ( struct usb_ep * ep , int halt , int wedge )
{
struct usbhsg_uep * uep = usbhsg_ep_to_uep ( ep ) ;
struct usbhs_pipe * pipe = usbhsg_uep_to_pipe ( uep ) ;
struct usbhsg_gpriv * gpriv = usbhsg_uep_to_gpriv ( uep ) ;
2011-06-06 14:18:38 +09:00
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
2011-04-05 11:40:54 +09:00
struct device * dev = usbhsg_gpriv_to_dev ( gpriv ) ;
unsigned long flags ;
2011-06-06 14:18:38 +09:00
usbhsg_pipe_disable ( uep ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
dev_dbg ( dev , " set halt %d (pipe %d) \n " ,
halt , usbhs_pipe_number ( pipe ) ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
/******************** spin lock ********************/
usbhs_lock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
if ( halt )
usbhs_pipe_stall ( pipe ) ;
else
usbhs_pipe_disable ( pipe ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
if ( halt & & wedge )
usbhsg_status_set ( gpriv , USBHSG_STATUS_WEDGE ) ;
else
usbhsg_status_clr ( gpriv , USBHSG_STATUS_WEDGE ) ;
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
usbhs_unlock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
/******************** spin unlock ******************/
2011-06-06 14:18:38 +09:00
return 0 ;
2011-04-05 11:40:54 +09:00
}
static int usbhsg_ep_set_halt ( struct usb_ep * ep , int value )
{
return __usbhsg_ep_set_halt_wedge ( ep , value , 0 ) ;
}
static int usbhsg_ep_set_wedge ( struct usb_ep * ep )
{
return __usbhsg_ep_set_halt_wedge ( ep , 1 , 1 ) ;
}
static struct usb_ep_ops usbhsg_ep_ops = {
. enable = usbhsg_ep_enable ,
. disable = usbhsg_ep_disable ,
. alloc_request = usbhsg_ep_alloc_request ,
. free_request = usbhsg_ep_free_request ,
. queue = usbhsg_ep_queue ,
. dequeue = usbhsg_ep_dequeue ,
. set_halt = usbhsg_ep_set_halt ,
. set_wedge = usbhsg_ep_set_wedge ,
} ;
/*
* usb module start / end
*/
static int usbhsg_try_start ( struct usbhs_priv * priv , u32 status )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
struct usbhsg_uep * dcp = usbhsg_gpriv_to_dcp ( gpriv ) ;
struct usbhs_mod * mod = usbhs_mod_get_current ( priv ) ;
struct device * dev = usbhs_priv_to_dev ( priv ) ;
unsigned long flags ;
2011-06-06 14:18:38 +09:00
int ret = 0 ;
2011-04-05 11:40:54 +09:00
/******************** spin lock ********************/
2011-06-06 14:18:38 +09:00
usbhs_lock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
usbhsg_status_set ( gpriv , status ) ;
if ( ! ( usbhsg_status_has ( gpriv , USBHSG_STATUS_STARTED ) & &
usbhsg_status_has ( gpriv , USBHSG_STATUS_REGISTERD ) ) )
2011-06-06 14:18:38 +09:00
ret = - 1 ; /* not ready */
usbhs_unlock ( priv , flags ) ;
/******************** spin unlock ********************/
if ( ret < 0 )
return 0 ; /* not ready is not error */
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
/*
* enable interrupt and systems if ready
*/
2011-04-05 11:40:54 +09:00
dev_dbg ( dev , " start gadget \n " ) ;
/*
* pipe initialize and enable DCP
*/
2011-06-06 14:18:07 +09:00
usbhs_pipe_init ( priv ,
2011-06-06 14:19:03 +09:00
usbhsg_dma_map_ctrl ) ;
2011-06-06 14:18:28 +09:00
usbhs_fifo_init ( priv ) ;
2011-06-06 14:18:38 +09:00
2012-12-10 22:44:07 -08:00
/* dcp init instead of usbhsg_ep_enable() */
2011-06-06 14:18:38 +09:00
dcp - > pipe = usbhs_dcp_malloc ( priv ) ;
dcp - > pipe - > mod_private = dcp ;
2011-10-10 22:04:00 -07:00
usbhs_pipe_config_update ( dcp - > pipe , 0 , 0 , 64 ) ;
2011-04-05 11:40:54 +09:00
/*
* system config enble
* - HI speed
* - function
* - usb module
*/
usbhs_sys_function_ctrl ( priv , 1 ) ;
/*
* enable irq callback
*/
mod - > irq_dev_state = usbhsg_irq_dev_state ;
mod - > irq_ctrl_stage = usbhsg_irq_ctrl_stage ;
usbhs_irq_callback_update ( priv , mod ) ;
return 0 ;
}
static int usbhsg_try_stop ( struct usbhs_priv * priv , u32 status )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
struct usbhs_mod * mod = usbhs_mod_get_current ( priv ) ;
struct usbhsg_uep * dcp = usbhsg_gpriv_to_dcp ( gpriv ) ;
struct device * dev = usbhs_priv_to_dev ( priv ) ;
unsigned long flags ;
2011-06-06 14:18:38 +09:00
int ret = 0 ;
2011-04-05 11:40:54 +09:00
/******************** spin lock ********************/
2011-06-06 14:18:38 +09:00
usbhs_lock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
usbhsg_status_clr ( gpriv , status ) ;
if ( ! usbhsg_status_has ( gpriv , USBHSG_STATUS_STARTED ) & &
! usbhsg_status_has ( gpriv , USBHSG_STATUS_REGISTERD ) )
2011-06-06 14:18:38 +09:00
ret = - 1 ; /* already done */
usbhs_unlock ( priv , flags ) ;
/******************** spin unlock ********************/
if ( ret < 0 )
return 0 ; /* already done is not error */
2011-04-05 11:40:54 +09:00
2011-06-06 14:18:38 +09:00
/*
* disable interrupt and systems if 1 st try
*/
2011-06-06 14:18:28 +09:00
usbhs_fifo_quit ( priv ) ;
2011-04-05 11:40:54 +09:00
/* disable all irq */
mod - > irq_dev_state = NULL ;
mod - > irq_ctrl_stage = NULL ;
usbhs_irq_callback_update ( priv , mod ) ;
gpriv - > gadget . speed = USB_SPEED_UNKNOWN ;
/* disable sys */
2011-11-24 17:28:35 -08:00
usbhs_sys_set_test_mode ( priv , 0 ) ;
2011-04-05 11:40:54 +09:00
usbhs_sys_function_ctrl ( priv , 0 ) ;
2012-12-10 22:44:07 -08:00
usbhsg_ep_disable ( & dcp - > ep ) ;
2011-04-05 11:40:54 +09:00
dev_dbg ( dev , " stop gadget \n " ) ;
return 0 ;
}
/*
*
* linux usb function
*
*/
2011-10-10 17:11:20 +03:00
static int usbhsg_gadget_start ( struct usb_gadget * gadget ,
struct usb_gadget_driver * driver )
2011-04-05 11:40:54 +09:00
{
2011-10-10 17:11:20 +03:00
struct usbhsg_gpriv * gpriv = usbhsg_gadget_to_gpriv ( gadget ) ;
2011-11-17 18:19:06 -08:00
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
2011-04-05 11:40:54 +09:00
2011-10-10 17:11:20 +03:00
if ( ! driver | |
2011-04-05 11:40:54 +09:00
! driver - > setup | |
2011-11-19 18:27:38 +01:00
driver - > max_speed < USB_SPEED_FULL )
2011-04-05 11:40:54 +09:00
return - EINVAL ;
2011-07-03 17:42:35 -07:00
2011-04-05 11:40:54 +09:00
/* first hook up the driver ... */
gpriv - > driver = driver ;
return usbhsg_try_start ( priv , USBHSG_STATUS_REGISTERD ) ;
}
2011-10-10 17:11:20 +03:00
static int usbhsg_gadget_stop ( struct usb_gadget * gadget ,
struct usb_gadget_driver * driver )
2011-04-05 11:40:54 +09:00
{
2011-10-10 17:11:20 +03:00
struct usbhsg_gpriv * gpriv = usbhsg_gadget_to_gpriv ( gadget ) ;
2011-11-17 18:19:06 -08:00
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
2011-04-05 11:40:54 +09:00
usbhsg_try_stop ( priv , USBHSG_STATUS_REGISTERD ) ;
gpriv - > driver = NULL ;
return 0 ;
}
/*
* usb gadget ops
*/
static int usbhsg_get_frame ( struct usb_gadget * gadget )
{
struct usbhsg_gpriv * gpriv = usbhsg_gadget_to_gpriv ( gadget ) ;
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
return usbhs_frame_get_num ( priv ) ;
}
2012-10-15 23:24:19 -07:00
static int usbhsg_pullup ( struct usb_gadget * gadget , int is_on )
{
struct usbhsg_gpriv * gpriv = usbhsg_gadget_to_gpriv ( gadget ) ;
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
usbhs_sys_function_pullup ( priv , is_on ) ;
return 0 ;
}
2012-03-16 13:10:15 +09:00
static int usbhsg_set_selfpowered ( struct usb_gadget * gadget , int is_self )
{
struct usbhsg_gpriv * gpriv = usbhsg_gadget_to_gpriv ( gadget ) ;
if ( is_self )
usbhsg_status_set ( gpriv , USBHSG_STATUS_SELF_POWERED ) ;
else
usbhsg_status_clr ( gpriv , USBHSG_STATUS_SELF_POWERED ) ;
return 0 ;
}
2013-01-24 17:58:16 +02:00
static const struct usb_gadget_ops usbhsg_gadget_ops = {
2011-04-05 11:40:54 +09:00
. get_frame = usbhsg_get_frame ,
2012-03-16 13:10:15 +09:00
. set_selfpowered = usbhsg_set_selfpowered ,
2011-10-10 17:11:20 +03:00
. udc_start = usbhsg_gadget_start ,
. udc_stop = usbhsg_gadget_stop ,
2012-10-15 23:24:19 -07:00
. pullup = usbhsg_pullup ,
2011-04-05 11:40:54 +09:00
} ;
static int usbhsg_start ( struct usbhs_priv * priv )
{
return usbhsg_try_start ( priv , USBHSG_STATUS_STARTED ) ;
}
static int usbhsg_stop ( struct usbhs_priv * priv )
{
2011-11-17 18:19:38 -08:00
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
/* cable disconnect */
if ( gpriv - > driver & &
gpriv - > driver - > disconnect )
gpriv - > driver - > disconnect ( & gpriv - > gadget ) ;
2011-04-05 11:40:54 +09:00
return usbhsg_try_stop ( priv , USBHSG_STATUS_STARTED ) ;
}
2011-10-26 19:33:49 -07:00
int usbhs_mod_gadget_probe ( struct usbhs_priv * priv )
2011-04-05 11:40:54 +09:00
{
struct usbhsg_gpriv * gpriv ;
struct usbhsg_uep * uep ;
struct device * dev = usbhs_priv_to_dev ( priv ) ;
int pipe_size = usbhs_get_dparam ( priv , pipe_size ) ;
int i ;
2011-06-28 16:33:47 +03:00
int ret ;
2011-04-05 11:40:54 +09:00
gpriv = kzalloc ( sizeof ( struct usbhsg_gpriv ) , GFP_KERNEL ) ;
if ( ! gpriv ) {
dev_err ( dev , " Could not allocate gadget priv \n " ) ;
return - ENOMEM ;
}
uep = kzalloc ( sizeof ( struct usbhsg_uep ) * pipe_size , GFP_KERNEL ) ;
if ( ! uep ) {
dev_err ( dev , " Could not allocate ep \n " ) ;
2011-06-28 16:33:47 +03:00
ret = - ENOMEM ;
2011-04-05 11:40:54 +09:00
goto usbhs_mod_gadget_probe_err_gpriv ;
}
/*
* CAUTION
*
* There is no guarantee that it is possible to access usb module here .
* Don ' t accesses to it .
* The accesse will be enable after " usbhsg_start "
*/
/*
* register itself
*/
usbhs_mod_register ( priv , & gpriv - > mod , USBHS_GADGET ) ;
/* init gpriv */
gpriv - > mod . name = " gadget " ;
gpriv - > mod . start = usbhsg_start ;
gpriv - > mod . stop = usbhsg_stop ;
gpriv - > uep = uep ;
gpriv - > uep_size = pipe_size ;
usbhsg_status_init ( gpriv ) ;
/*
* init gadget
*/
gpriv - > gadget . dev . parent = dev ;
gpriv - > gadget . name = " renesas_usbhs_udc " ;
gpriv - > gadget . ops = & usbhsg_gadget_ops ;
2011-11-19 18:27:37 +01:00
gpriv - > gadget . max_speed = USB_SPEED_HIGH ;
2011-04-05 11:40:54 +09:00
INIT_LIST_HEAD ( & gpriv - > gadget . ep_list ) ;
/*
* init usb_ep
*/
usbhsg_for_each_uep_with_dcp ( uep , gpriv , i ) {
uep - > gpriv = gpriv ;
2012-12-10 22:43:45 -08:00
uep - > pipe = NULL ;
2011-04-05 11:40:54 +09:00
snprintf ( uep - > ep_name , EP_NAME_SIZE , " ep%d " , i ) ;
uep - > ep . name = uep - > ep_name ;
uep - > ep . ops = & usbhsg_ep_ops ;
INIT_LIST_HEAD ( & uep - > ep . ep_list ) ;
/* init DCP */
if ( usbhsg_is_dcp ( uep ) ) {
gpriv - > gadget . ep0 = & uep - > ep ;
2013-12-13 12:23:38 +01:00
usb_ep_set_maxpacket_limit ( & uep - > ep , 64 ) ;
2011-04-05 11:40:54 +09:00
}
/* init normal pipe */
else {
2013-12-13 12:23:38 +01:00
usb_ep_set_maxpacket_limit ( & uep - > ep , 512 ) ;
2011-04-05 11:40:54 +09:00
list_add_tail ( & uep - > ep . ep_list , & gpriv - > gadget . ep_list ) ;
}
}
2011-06-28 16:33:47 +03:00
ret = usb_add_gadget_udc ( dev , & gpriv - > gadget ) ;
if ( ret )
2013-01-24 17:08:01 +02:00
goto err_add_udc ;
2011-06-28 16:33:47 +03:00
2011-04-05 11:40:54 +09:00
dev_info ( dev , " gadget probed \n " ) ;
return 0 ;
2011-11-17 18:19:06 -08:00
2011-06-28 16:33:47 +03:00
err_add_udc :
kfree ( gpriv - > uep ) ;
2011-04-05 11:40:54 +09:00
usbhs_mod_gadget_probe_err_gpriv :
kfree ( gpriv ) ;
2011-06-28 16:33:47 +03:00
return ret ;
2011-04-05 11:40:54 +09:00
}
2011-10-26 19:33:49 -07:00
void usbhs_mod_gadget_remove ( struct usbhs_priv * priv )
2011-04-05 11:40:54 +09:00
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
2011-06-28 16:33:47 +03:00
usb_del_gadget_udc ( & gpriv - > gadget ) ;
2011-07-03 17:42:35 -07:00
2011-06-03 19:50:48 +02:00
kfree ( gpriv - > uep ) ;
2011-04-05 11:40:54 +09:00
kfree ( gpriv ) ;
}