2017-11-03 11:28:30 +01:00
// SPDX-License-Identifier: GPL-1.0+
2011-04-05 11:40:54 +09:00
/*
* Renesas USB driver
*
* Copyright ( C ) 2011 Renesas Solutions Corp .
2019-06-25 14:38:46 +09:00
* Copyright ( C ) 2019 Renesas Electronics Corporation
2011-04-05 11:40:54 +09:00
* Kuninori Morimoto < kuninori . morimoto . gx @ renesas . com >
*/
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>
2015-07-13 16:30:18 +01:00
# include <linux/usb/otg.h>
2011-04-05 11:40:54 +09:00
# 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 ;
2017-07-19 16:16:55 +09:00
spinlock_t lock ; /* protect the pipe */
2011-04-05 11:40:54 +09:00
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 ;
2015-07-13 16:30:18 +01:00
struct usb_phy * transceiver ;
bool vbus_active ;
2011-04-05 11:40:54 +09:00
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)
2014-11-04 10:05:43 +09:00
# define USBHSG_STATUS_SOFT_CONNECT (1 << 4)
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
*/
2015-03-16 16:36:48 +09:00
static void __usbhsg_queue_pop ( struct usbhsg_uep * uep ,
struct usbhsg_request * ureq ,
int status )
2011-04-05 11:40:54 +09:00
{
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 ) ;
2015-03-16 16:36:48 +09:00
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
2011-04-05 11:40:54 +09:00
2015-11-18 14:33:35 +09:00
if ( pipe )
dev_dbg ( dev , " pipe %d : queue pop \n " , usbhs_pipe_number ( pipe ) ) ;
2011-04-05 11:40:54 +09:00
ureq - > req . status = status ;
2015-03-16 16:36:48 +09:00
spin_unlock ( usbhs_priv_to_lock ( priv ) ) ;
2014-09-24 22:43:19 +02:00
usb_gadget_giveback_request ( & uep - > ep , & ureq - > req ) ;
2015-03-16 16:36:48 +09:00
spin_lock ( usbhs_priv_to_lock ( priv ) ) ;
}
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_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
unsigned long flags ;
usbhs_lock ( priv , flags ) ;
__usbhsg_queue_pop ( uep , ureq , status ) ;
usbhs_unlock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
}
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 ) ;
2016-04-04 20:40:20 +09:00
unsigned long flags ;
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
2016-04-04 20:40:20 +09:00
usbhs_lock ( priv , flags ) ;
if ( uep )
__usbhsg_queue_pop ( uep , ureq , 0 ) ;
usbhs_unlock ( priv , flags ) ;
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
*/
2016-04-18 16:53:41 +09:00
static int usbhsg_dma_map_ctrl ( struct device * dma_dev , 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 ;
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 ) ;
2016-04-18 16:53:42 +09:00
ret = usb_gadget_map_request_by_dev ( dma_dev , req , dir ) ;
2011-12-19 11:57:16 +02:00
if ( ret < 0 )
return ret ;
pkt - > dma = req - > dma ;
} else {
2016-04-18 16:53:42 +09:00
usb_gadget_unmap_request_by_dev ( dma_dev , req , dir ) ;
2011-12-19 11:57:16 +02:00
}
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 ) ;
2019-10-16 13:14:33 +09:00
usbhs_sys_set_test_mode ( priv , le16_to_cpu ( ctrl - > wIndex ) > > 8 ) ;
2011-11-24 17:28:35 -08:00
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 ;
2019-10-15 16:30:17 +01:00
__le16 * buf ;
2011-11-24 17:28:04 -08:00
/* 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 ) ;
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 ) ;
2019-09-11 15:15:56 +02:00
int state = usbhs_status_get_device_state ( irq_state ) ;
2011-04-05 11:40:54 +09:00
2011-10-10 22:01:51 -07:00
gpriv - > gadget . speed = usbhs_bus_get_speed ( priv ) ;
2011-04-05 11:40:54 +09:00
2019-09-11 15:15:56 +02:00
dev_dbg ( dev , " state = %x : speed : %d \n " , state , gpriv - > gadget . speed ) ;
if ( gpriv - > gadget . speed ! = USB_SPEED_UNKNOWN & &
( state & SUSPENDED_STATE ) ) {
if ( gpriv - > driver & & gpriv - > driver - > suspend )
gpriv - > driver - > suspend ( & gpriv - > gadget ) ;
usb_gadget_set_state ( & gpriv - > gadget , USB_STATE_SUSPENDED ) ;
}
2011-04-05 11:40:54 +09:00
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 ;
2014-11-04 10:05:44 +09:00
case READ_STATUS_STAGE :
case WRITE_STATUS_STAGE :
usbhs_dcp_control_transfer_done ( pipe ) ;
2020-07-07 14:56:07 -05:00
fallthrough ;
2011-04-05 11:40:54 +09:00
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
2016-03-03 18:35:51 +09:00
usbhsg_queue_pop ( uep , usbhsg_pkt_to_ureq ( pkt ) , - ESHUTDOWN ) ;
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 ;
2016-06-08 16:32:50 +09:00
unsigned long flags ;
usbhs_lock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
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 ) ;
2016-06-08 16:32:50 +09:00
ret = 0 ;
goto usbhsg_ep_enable_end ;
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 .
*/
2016-08-08 21:50:52 +09:00
if ( usb_endpoint_dir_in ( desc ) ) {
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_fifo_dma_push_handler ;
2016-08-08 21:50:52 +09:00
} else {
2011-10-10 22:00:59 -07:00
pipe - > handler = & usbhs_fifo_dma_pop_handler ;
2016-08-08 21:50:52 +09:00
usbhs_xxxsts_clear ( priv , BRDYSTS ,
usbhs_pipe_number ( pipe ) ) ;
}
2011-04-05 11:40:54 +09:00
ret = 0 ;
}
2011-04-21 14:10:08 +09:00
2016-06-08 16:32:50 +09:00
usbhsg_ep_enable_end :
usbhs_unlock ( priv , flags ) ;
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 ) ;
2017-07-19 16:16:55 +09:00
struct usbhs_pipe * pipe ;
unsigned long flags ;
2011-04-05 11:40:54 +09:00
2017-07-19 16:16:55 +09:00
spin_lock_irqsave ( & uep - > lock , flags ) ;
pipe = usbhsg_uep_to_pipe ( uep ) ;
2017-07-28 19:28:57 +09:00
if ( ! pipe )
2017-07-19 16:16:55 +09:00
goto out ;
2014-11-04 10:05:42 +09:00
2012-12-10 22:44:07 -08:00
usbhsg_pipe_disable ( uep ) ;
2014-07-09 20:30:13 +09:00
usbhs_pipe_free ( pipe ) ;
2012-12-10 22:44:07 -08:00
uep - > pipe - > mod_private = NULL ;
uep - > pipe = NULL ;
2017-07-19 16:16:55 +09:00
out :
spin_unlock_irqrestore ( & uep - > lock , flags ) ;
2012-12-10 22:44:07 -08:00
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 ) ;
2017-07-19 16:16:55 +09:00
struct usbhs_pipe * pipe ;
unsigned long flags ;
2011-04-05 11:40:54 +09:00
2017-07-19 16:16:55 +09:00
spin_lock_irqsave ( & uep - > lock , flags ) ;
pipe = usbhsg_uep_to_pipe ( uep ) ;
2015-11-18 14:33:35 +09:00
if ( pipe )
usbhs_pkt_pop ( pipe , usbhsg_ureq_to_pkt ( ureq ) ) ;
/*
* To dequeue a request , this driver should call the usbhsg_queue_pop ( )
* even if the pipe is NULL .
*/
2011-04-05 11:40:54 +09:00
usbhsg_queue_pop ( uep , ureq , - ECONNRESET ) ;
2017-07-19 16:16:55 +09:00
spin_unlock_irqrestore ( & uep - > lock , flags ) ;
2011-04-05 11:40:54 +09:00
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 ;
2019-10-01 19:10:33 +09:00
int ret = 0 ;
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
2019-10-01 19:10:33 +09:00
/*
* According to usb_ep_set_halt ( ) ' s description , this function should
* return - EAGAIN if the IN endpoint has any queue or data . Note
* that the usbhs_pipe_is_dir_in ( ) returns false if the pipe is an
* IN endpoint in the gadget mode .
*/
if ( ! usbhs_pipe_is_dir_in ( pipe ) & & ( __usbhsf_pkt_get ( pipe ) | |
usbhs_pipe_contains_transmittable_data ( pipe ) ) ) {
ret = - EAGAIN ;
goto out ;
}
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
2019-10-01 19:10:33 +09:00
out :
2011-06-06 14:18:38 +09:00
usbhs_unlock ( priv , flags ) ;
2011-04-05 11:40:54 +09:00
/******************** spin unlock ******************/
2019-10-01 19:10:33 +09:00
return ret ;
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 ) ;
}
2017-08-12 17:34:53 +05:30
static const struct usb_ep_ops usbhsg_ep_ops = {
2011-04-05 11:40:54 +09:00
. 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 ,
} ;
2014-11-04 10:05:43 +09:00
/*
* pullup control
*/
static int usbhsg_can_pullup ( struct usbhs_priv * priv )
{
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
return gpriv - > driver & &
usbhsg_status_has ( gpriv , USBHSG_STATUS_SOFT_CONNECT ) ;
}
static void usbhsg_update_pullup ( struct usbhs_priv * priv )
{
if ( usbhsg_can_pullup ( priv ) )
usbhs_sys_function_pullup ( priv , 1 ) ;
else
usbhs_sys_function_pullup ( priv , 0 ) ;
}
2011-04-05 11:40:54 +09:00
/*
* 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
*/
2014-11-04 10:05:45 +09:00
usbhs_fifo_init ( priv ) ;
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: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 ) ;
2014-11-04 10:05:43 +09:00
usbhsg_update_pullup ( priv ) ;
2011-04-05 11:40:54 +09:00
/*
* 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 ) ;
2017-07-19 16:16:55 +09:00
struct usbhsg_uep * uep ;
2011-04-05 11:40:54 +09:00
struct device * dev = usbhs_priv_to_dev ( priv ) ;
unsigned long flags ;
2017-07-19 16:16:55 +09:00
int ret = 0 , i ;
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 ) ;
2017-07-19 16:16:55 +09:00
/* disable all eps */
usbhsg_for_each_uep_with_dcp ( uep , gpriv , i )
usbhsg_ep_disable ( & uep - > ep ) ;
2011-04-05 11:40:54 +09:00
dev_dbg ( dev , " stop gadget \n " ) ;
return 0 ;
}
2015-07-13 16:30:18 +01:00
/*
* VBUS provided by the PHY
*/
static int usbhsm_phy_get_vbus ( struct platform_device * pdev )
{
struct usbhs_priv * priv = usbhs_pdev_to_priv ( pdev ) ;
struct usbhsg_gpriv * gpriv = usbhsg_priv_to_gpriv ( priv ) ;
return gpriv - > vbus_active ;
}
static void usbhs_mod_phy_mode ( struct usbhs_priv * priv )
{
struct usbhs_mod_info * info = & priv - > mod_info ;
2019-06-25 14:38:48 +09:00
info - > irq_vbus = NULL ;
info - > get_vbus = usbhsm_phy_get_vbus ;
2015-07-13 16:30:18 +01:00
usbhs_irq_callback_update ( priv , NULL ) ;
}
2011-04-05 11:40:54 +09:00
/*
*
* 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 ) ;
2015-07-13 16:30:18 +01:00
struct device * dev = usbhs_priv_to_dev ( priv ) ;
int ret ;
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
2015-07-13 16:30:18 +01:00
/* connect to bus through transceiver */
if ( ! IS_ERR_OR_NULL ( gpriv - > transceiver ) ) {
ret = otg_set_peripheral ( gpriv - > transceiver - > otg ,
& gpriv - > gadget ) ;
if ( ret ) {
dev_err ( dev , " %s: can't bind to transceiver \n " ,
gpriv - > gadget . name ) ;
return ret ;
}
/* get vbus using phy versions */
usbhs_mod_phy_mode ( priv ) ;
}
2011-04-05 11:40:54 +09:00
/* first hook up the driver ... */
gpriv - > driver = driver ;
return usbhsg_try_start ( priv , USBHSG_STATUS_REGISTERD ) ;
}
2014-10-17 12:05:12 -05:00
static int usbhsg_gadget_stop ( struct usb_gadget * gadget )
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 ) ;
2015-07-13 16:30:18 +01:00
if ( ! IS_ERR_OR_NULL ( gpriv - > transceiver ) )
otg_set_peripheral ( gpriv - > transceiver - > otg , NULL ) ;
2011-04-05 11:40:54 +09:00
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 ) ;
2014-11-04 10:05:43 +09:00
unsigned long flags ;
2012-10-15 23:24:19 -07:00
2014-11-04 10:05:43 +09:00
usbhs_lock ( priv , flags ) ;
if ( is_on )
usbhsg_status_set ( gpriv , USBHSG_STATUS_SOFT_CONNECT ) ;
else
usbhsg_status_clr ( gpriv , USBHSG_STATUS_SOFT_CONNECT ) ;
usbhsg_update_pullup ( priv ) ;
usbhs_unlock ( priv , flags ) ;
2012-10-15 23:24:19 -07:00
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 ) ;
2015-01-28 16:32:28 +08:00
gadget - > is_selfpowered = ( is_self ! = 0 ) ;
2012-03-16 13:10:15 +09:00
return 0 ;
}
2015-07-13 16:30:18 +01:00
static int usbhsg_vbus_session ( struct usb_gadget * gadget , int is_active )
{
struct usbhsg_gpriv * gpriv = usbhsg_gadget_to_gpriv ( gadget ) ;
struct usbhs_priv * priv = usbhsg_gpriv_to_priv ( gpriv ) ;
struct platform_device * pdev = usbhs_priv_to_pdev ( priv ) ;
gpriv - > vbus_active = ! ! is_active ;
2019-06-25 14:38:46 +09:00
usbhsc_schedule_notify_hotplug ( pdev ) ;
2015-07-13 16:30:18 +01:00
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 ,
2015-07-13 16:30:18 +01:00
. vbus_session = usbhsg_vbus_session ,
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 ) ;
2015-11-18 14:34:10 +09:00
struct renesas_usbhs_driver_pipe_config * pipe_configs =
usbhs_get_dparam ( priv , pipe_configs ) ;
2011-04-05 11:40:54 +09:00
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 ) ;
2016-08-25 19:39:28 +02:00
if ( ! gpriv )
2011-04-05 11:40:54 +09:00
return - ENOMEM ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:03:40 -07:00
uep = kcalloc ( pipe_size , sizeof ( struct usbhsg_uep ) , GFP_KERNEL ) ;
2011-04-05 11:40:54 +09:00
if ( ! uep ) {
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 ;
}
2015-07-13 16:30:18 +01:00
gpriv - > transceiver = usb_get_phy ( USB_PHY_TYPE_UNDEFINED ) ;
dev_info ( dev , " %stransceiver found \n " ,
2016-08-13 01:28:24 +00:00
! IS_ERR ( gpriv - > transceiver ) ? " " : " no " ) ;
2015-07-13 16:30:18 +01:00
2011-04-05 11:40:54 +09:00
/*
* 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 ;
2016-08-22 17:48:28 +09:00
gpriv - > gadget . quirk_avoids_skb_reserve = usbhs_get_dparam ( priv ,
has_usb_dmac ) ;
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 ) ;
2017-08-09 19:55:24 +09:00
spin_lock_init ( & uep - > lock ) ;
2011-04-05 11:40:54 +09:00
/* 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 ) ;
2015-07-31 16:00:47 +02:00
uep - > ep . caps . type_control = true ;
2015-11-18 14:34:10 +09:00
} else {
/* init normal pipe */
if ( pipe_configs [ i ] . type = = USB_ENDPOINT_XFER_ISOC )
uep - > ep . caps . type_iso = true ;
if ( pipe_configs [ i ] . type = = USB_ENDPOINT_XFER_BULK )
uep - > ep . caps . type_bulk = true ;
if ( pipe_configs [ i ] . type = = USB_ENDPOINT_XFER_INT )
uep - > ep . caps . type_int = true ;
usb_ep_set_maxpacket_limit ( & uep - > ep ,
pipe_configs [ i ] . bufsize ) ;
2011-04-05 11:40:54 +09:00
list_add_tail ( & uep - > ep . ep_list , & gpriv - > gadget . ep_list ) ;
}
2015-07-31 16:00:47 +02:00
uep - > ep . caps . dir_in = true ;
uep - > ep . caps . dir_out = true ;
2011-04-05 11:40:54 +09:00
}
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 ) ;
}