2012-05-11 18:25:46 +04:00
/*
* ci . h - common structures , functions , and macros of the ChipIdea driver
*
* Copyright ( C ) 2008 Chipidea - MIPS Technologies , Inc . All rights reserved .
*
* Author : David Lopo
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# ifndef __DRIVERS_USB_CHIPIDEA_CI_H
# define __DRIVERS_USB_CHIPIDEA_CI_H
# include <linux/list.h>
2012-05-11 18:25:47 +04:00
# include <linux/irqreturn.h>
2012-05-11 18:25:54 +04:00
# include <linux/usb.h>
2012-05-11 18:25:46 +04:00
# include <linux/usb/gadget.h>
2014-04-23 11:56:44 +04:00
# include <linux/usb/otg-fsm.h>
2012-05-11 18:25:46 +04:00
/******************************************************************************
* DEFINE
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-03-30 14:54:10 +04:00
# define TD_PAGE_COUNT 5
2013-06-24 15:46:36 +04:00
# define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
2012-05-11 18:25:46 +04:00
# define ENDPT_MAX 32
2014-01-06 06:10:38 +04:00
/******************************************************************************
* REGISTERS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-02-11 07:44:54 +03:00
/* Identification Registers */
# define ID_ID 0x0
# define ID_HWGENERAL 0x4
# define ID_HWHOST 0x8
# define ID_HWDEVICE 0xc
# define ID_HWTXBUF 0x10
# define ID_HWRXBUF 0x14
# define ID_SBUSCFG 0x90
2014-01-06 06:10:38 +04:00
/* register indices */
enum ci_hw_regs {
CAP_CAPLENGTH ,
CAP_HCCPARAMS ,
CAP_DCCPARAMS ,
CAP_TESTMODE ,
CAP_LAST = CAP_TESTMODE ,
OP_USBCMD ,
OP_USBSTS ,
OP_USBINTR ,
OP_DEVICEADDR ,
OP_ENDPTLISTADDR ,
OP_PORTSC ,
OP_DEVLC ,
OP_OTGSC ,
OP_USBMODE ,
OP_ENDPTSETUPSTAT ,
OP_ENDPTPRIME ,
OP_ENDPTFLUSH ,
OP_ENDPTSTAT ,
OP_ENDPTCOMPLETE ,
OP_ENDPTCTRL ,
/* endptctrl1..15 follow */
OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2 ,
} ;
2012-05-11 18:25:46 +04:00
/******************************************************************************
* STRUCTURES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-05-11 18:25:49 +04:00
/**
2013-06-24 15:46:36 +04:00
* struct ci_hw_ep - endpoint representation
2012-05-11 18:25:49 +04:00
* @ ep : endpoint structure for gadget drivers
* @ dir : endpoint direction ( TX / RX )
* @ num : endpoint number
* @ type : endpoint type
* @ name : string description of the endpoint
* @ qh : queue head for this endpoint
* @ wedge : is the endpoint wedged
2012-07-07 18:56:40 +04:00
* @ ci : pointer to the controller
2012-05-11 18:25:49 +04:00
* @ lock : pointer to controller ' s spinlock
* @ td_pool : pointer to controller ' s TD pool
*/
2013-06-24 15:46:36 +04:00
struct ci_hw_ep {
2012-05-11 18:25:49 +04:00
struct usb_ep ep ;
u8 dir ;
u8 num ;
u8 type ;
char name [ 16 ] ;
2012-05-11 18:25:46 +04:00
struct {
2012-05-11 18:25:49 +04:00
struct list_head queue ;
2013-06-24 15:46:36 +04:00
struct ci_hw_qh * ptr ;
2012-05-11 18:25:49 +04:00
dma_addr_t dma ;
} qh ;
int wedge ;
2012-05-11 18:25:46 +04:00
/* global resources */
2013-06-24 15:46:36 +04:00
struct ci_hdrc * ci ;
2012-05-11 18:25:49 +04:00
spinlock_t * lock ;
struct dma_pool * td_pool ;
2013-06-13 18:59:54 +04:00
struct td_node * pending_td ;
2012-05-11 18:25:46 +04:00
} ;
2012-05-11 18:25:47 +04:00
enum ci_role {
CI_ROLE_HOST = 0 ,
CI_ROLE_GADGET ,
CI_ROLE_END ,
} ;
2015-02-11 07:44:55 +03:00
enum ci_revision {
CI_REVISION_1X = 10 , /* Revision 1.x */
CI_REVISION_20 = 20 , /* Revision 2.0 */
CI_REVISION_21 , /* Revision 2.1 */
CI_REVISION_22 , /* Revision 2.2 */
CI_REVISION_23 , /* Revision 2.3 */
CI_REVISION_24 , /* Revision 2.4 */
CI_REVISION_25 , /* Revision 2.5 */
CI_REVISION_25_PLUS , /* Revision above than 2.5 */
CI_REVISION_UNKNOWN = 99 , /* Unknown Revision */
} ;
2012-05-11 18:25:47 +04:00
/**
* struct ci_role_driver - host / gadget role driver
2014-09-22 04:14:17 +04:00
* @ start : start this role
* @ stop : stop this role
* @ irq : irq handler for this role
* @ name : role name string ( host / gadget )
2012-05-11 18:25:47 +04:00
*/
struct ci_role_driver {
2013-06-24 15:46:36 +04:00
int ( * start ) ( struct ci_hdrc * ) ;
void ( * stop ) ( struct ci_hdrc * ) ;
irqreturn_t ( * irq ) ( struct ci_hdrc * ) ;
2012-05-11 18:25:47 +04:00
const char * name ;
} ;
2012-05-11 18:25:49 +04:00
/**
* struct hw_bank - hardware register mapping representation
* @ lpm : set if the device is LPM capable
2012-05-11 18:25:54 +04:00
* @ phys : physical address of the controller ' s registers
2012-05-11 18:25:49 +04:00
* @ abs : absolute address of the beginning of register window
* @ cap : capability registers
* @ op : operational registers
* @ size : size of the register window
* @ regmap : register lookup table
*/
2012-05-11 18:25:46 +04:00
struct hw_bank {
2012-05-11 18:25:49 +04:00
unsigned lpm ;
2012-05-11 18:25:54 +04:00
resource_size_t phys ;
2012-05-11 18:25:49 +04:00
void __iomem * abs ;
void __iomem * cap ;
void __iomem * op ;
size_t size ;
2014-01-06 06:10:38 +04:00
void __iomem * regmap [ OP_LAST + 1 ] ;
2012-05-11 18:25:46 +04:00
} ;
2012-05-11 18:25:49 +04:00
/**
2013-06-24 15:46:36 +04:00
* struct ci_hdrc - chipidea device representation
2012-05-11 18:25:49 +04:00
* @ dev : pointer to parent device
* @ lock : access synchronization
* @ hw_bank : hardware register mapping
* @ irq : IRQ number
* @ roles : array of supported roles for this controller
* @ role : current role
* @ is_otg : if the device is otg - capable
2014-04-23 11:56:44 +04:00
* @ fsm : otg finite state machine
2014-04-23 11:56:48 +04:00
* @ fsm_timer : pointer to timer list of otg fsm
2012-05-11 18:25:49 +04:00
* @ work : work for role changing
* @ wq : workqueue thread
* @ qh_pool : allocation pool for queue heads
* @ td_pool : allocation pool for transfer descriptors
* @ gadget : device side representation for peripheral controller
* @ driver : gadget driver
* @ hw_ep_max : total number of endpoints supported by hardware
2013-06-24 15:46:36 +04:00
* @ ci_hw_ep : array of endpoints
2012-05-11 18:25:49 +04:00
* @ ep0_dir : ep0 direction
* @ ep0out : pointer to ep0 OUT endpoint
* @ ep0in : pointer to ep0 IN endpoint
* @ status : ep0 status request
* @ setaddr : if we should set the address on status completion
* @ address : usb address received from the host
* @ remote_wakeup : host - enabled remote wakeup
* @ suspended : suspended by host
* @ test_mode : the selected test mode
2012-06-29 13:48:53 +04:00
* @ platdata : platform specific information supplied by parent device
2012-05-11 18:25:49 +04:00
* @ vbus_active : is VBUS active
2014-10-30 20:41:19 +03:00
* @ phy : pointer to PHY , if any
* @ usb_phy : pointer to USB PHY , if any and if using the USB PHY framework
2012-05-11 18:25:54 +04:00
* @ hcd : pointer to usb_hcd for ehci host driver
2013-03-30 14:53:51 +04:00
* @ debugfs : root dentry for this controller in debugfs
2013-08-14 13:44:11 +04:00
* @ id_event : indicates there is an id event , and handled at ci_otg_work
* @ b_sess_valid_event : indicates there is a vbus event , and handled
* at ci_otg_work
2014-01-10 09:51:27 +04:00
* @ imx28_write_fix : Freescale imx28 needs swp instruction for writing
2015-02-11 07:44:45 +03:00
* @ supports_runtime_pm : if runtime pm is supported
* @ in_lpm : if the core in low power mode
* @ wakeup_int : if wakeup interrupt occur
2015-02-11 07:44:55 +03:00
* @ rev : The revision number for controller
2012-05-11 18:25:49 +04:00
*/
2013-06-24 15:46:36 +04:00
struct ci_hdrc {
2012-05-11 18:25:49 +04:00
struct device * dev ;
spinlock_t lock ;
struct hw_bank hw_bank ;
int irq ;
struct ci_role_driver * roles [ CI_ROLE_END ] ;
enum ci_role role ;
bool is_otg ;
2014-10-30 20:41:16 +03:00
struct usb_otg otg ;
2014-04-23 11:56:44 +04:00
struct otg_fsm fsm ;
2014-04-23 11:56:48 +04:00
struct ci_otg_fsm_timer_list * fsm_timer ;
2012-05-11 18:25:49 +04:00
struct work_struct work ;
struct workqueue_struct * wq ;
struct dma_pool * qh_pool ;
struct dma_pool * td_pool ;
struct usb_gadget gadget ;
struct usb_gadget_driver * driver ;
unsigned hw_ep_max ;
2013-06-24 15:46:36 +04:00
struct ci_hw_ep ci_hw_ep [ ENDPT_MAX ] ;
2012-05-11 18:25:49 +04:00
u32 ep0_dir ;
2013-06-24 15:46:36 +04:00
struct ci_hw_ep * ep0out , * ep0in ;
2012-05-11 18:25:49 +04:00
struct usb_request * status ;
bool setaddr ;
u8 address ;
u8 remote_wakeup ;
u8 suspended ;
u8 test_mode ;
2013-06-24 15:46:36 +04:00
struct ci_hdrc_platform_data * platdata ;
2012-05-11 18:25:49 +04:00
int vbus_active ;
2014-10-30 20:41:19 +03:00
struct phy * phy ;
/* old usb_phy interface */
2014-10-30 20:41:16 +03:00
struct usb_phy * usb_phy ;
2012-05-11 18:25:54 +04:00
struct usb_hcd * hcd ;
2013-03-30 14:53:51 +04:00
struct dentry * debugfs ;
2013-08-14 13:44:11 +04:00
bool id_event ;
bool b_sess_valid_event ;
2014-01-10 09:51:27 +04:00
bool imx28_write_fix ;
2015-02-11 07:44:45 +03:00
bool supports_runtime_pm ;
bool in_lpm ;
bool wakeup_int ;
2015-02-11 07:44:55 +03:00
enum ci_revision rev ;
2012-05-11 18:25:46 +04:00
} ;
2013-06-24 15:46:36 +04:00
static inline struct ci_role_driver * ci_role ( struct ci_hdrc * ci )
2012-05-11 18:25:47 +04:00
{
BUG_ON ( ci - > role > = CI_ROLE_END | | ! ci - > roles [ ci - > role ] ) ;
return ci - > roles [ ci - > role ] ;
}
2013-06-24 15:46:36 +04:00
static inline int ci_role_start ( struct ci_hdrc * ci , enum ci_role role )
2012-05-11 18:25:47 +04:00
{
int ret ;
if ( role > = CI_ROLE_END )
return - EINVAL ;
if ( ! ci - > roles [ role ] )
return - ENXIO ;
ret = ci - > roles [ role ] - > start ( ci ) ;
if ( ! ret )
ci - > role = role ;
return ret ;
}
2013-06-24 15:46:36 +04:00
static inline void ci_role_stop ( struct ci_hdrc * ci )
2012-05-11 18:25:47 +04:00
{
enum ci_role role = ci - > role ;
if ( role = = CI_ROLE_END )
return ;
ci - > role = CI_ROLE_END ;
ci - > roles [ role ] - > stop ( ci ) ;
}
2015-02-11 07:44:54 +03:00
/**
* hw_read_id_reg : reads from a identification register
* @ ci : the controller
* @ offset : offset from the beginning of identification registers region
* @ mask : bitfield mask
*
* This function returns register contents
*/
static inline u32 hw_read_id_reg ( struct ci_hdrc * ci , u32 offset , u32 mask )
{
return ioread32 ( ci - > hw_bank . abs + offset ) & mask ;
}
/**
* hw_write_id_reg : writes to a identification register
* @ ci : the controller
* @ offset : offset from the beginning of identification registers region
* @ mask : bitfield mask
* @ data : new value
*/
static inline void hw_write_id_reg ( struct ci_hdrc * ci , u32 offset ,
u32 mask , u32 data )
{
if ( ~ mask )
data = ( ioread32 ( ci - > hw_bank . abs + offset ) & ~ mask )
| ( data & mask ) ;
iowrite32 ( data , ci - > hw_bank . abs + offset ) ;
}
2012-05-11 18:25:46 +04:00
/**
* hw_read : reads from a hw register
2014-09-22 04:14:17 +04:00
* @ ci : the controller
2012-05-11 18:25:46 +04:00
* @ reg : register index
* @ mask : bitfield mask
*
* This function returns register contents
*/
2013-06-24 15:46:36 +04:00
static inline u32 hw_read ( struct ci_hdrc * ci , enum ci_hw_regs reg , u32 mask )
2012-05-11 18:25:46 +04:00
{
2012-07-07 18:56:40 +04:00
return ioread32 ( ci - > hw_bank . regmap [ reg ] ) & mask ;
2012-05-11 18:25:46 +04:00
}
2014-01-10 09:51:27 +04:00
# ifdef CONFIG_SOC_IMX28
static inline void imx28_ci_writel ( u32 val , volatile void __iomem * addr )
{
__asm__ ( " swp %0, %0, [%1] " : : " r " ( val ) , " r " ( addr ) ) ;
}
# else
static inline void imx28_ci_writel ( u32 val , volatile void __iomem * addr )
{
}
# endif
static inline void __hw_write ( struct ci_hdrc * ci , u32 val ,
void __iomem * addr )
{
if ( ci - > imx28_write_fix )
imx28_ci_writel ( val , addr ) ;
else
iowrite32 ( val , addr ) ;
}
2012-05-11 18:25:46 +04:00
/**
* hw_write : writes to a hw register
2014-09-22 04:14:17 +04:00
* @ ci : the controller
2012-05-11 18:25:46 +04:00
* @ reg : register index
* @ mask : bitfield mask
* @ data : new value
*/
2013-06-24 15:46:36 +04:00
static inline void hw_write ( struct ci_hdrc * ci , enum ci_hw_regs reg ,
2012-05-11 18:25:46 +04:00
u32 mask , u32 data )
{
if ( ~ mask )
2012-07-07 18:56:40 +04:00
data = ( ioread32 ( ci - > hw_bank . regmap [ reg ] ) & ~ mask )
2012-05-11 18:25:46 +04:00
| ( data & mask ) ;
2014-01-10 09:51:27 +04:00
__hw_write ( ci , data , ci - > hw_bank . regmap [ reg ] ) ;
2012-05-11 18:25:46 +04:00
}
/**
* hw_test_and_clear : tests & clears a hw register
2014-09-22 04:14:17 +04:00
* @ ci : the controller
2012-05-11 18:25:46 +04:00
* @ reg : register index
* @ mask : bitfield mask
*
* This function returns register contents
*/
2013-06-24 15:46:36 +04:00
static inline u32 hw_test_and_clear ( struct ci_hdrc * ci , enum ci_hw_regs reg ,
2012-05-11 18:25:46 +04:00
u32 mask )
{
2012-07-07 18:56:40 +04:00
u32 val = ioread32 ( ci - > hw_bank . regmap [ reg ] ) & mask ;
2012-05-11 18:25:46 +04:00
2014-01-10 09:51:27 +04:00
__hw_write ( ci , val , ci - > hw_bank . regmap [ reg ] ) ;
2012-05-11 18:25:46 +04:00
return val ;
}
/**
* hw_test_and_write : tests & writes a hw register
2014-09-22 04:14:17 +04:00
* @ ci : the controller
2012-05-11 18:25:46 +04:00
* @ reg : register index
* @ mask : bitfield mask
* @ data : new value
*
* This function returns register contents
*/
2013-06-24 15:46:36 +04:00
static inline u32 hw_test_and_write ( struct ci_hdrc * ci , enum ci_hw_regs reg ,
2012-05-11 18:25:46 +04:00
u32 mask , u32 data )
{
2012-07-07 18:56:40 +04:00
u32 val = hw_read ( ci , reg , ~ 0 ) ;
2012-05-11 18:25:46 +04:00
2012-07-07 18:56:40 +04:00
hw_write ( ci , reg , mask , data ) ;
2013-03-30 14:53:55 +04:00
return ( val & mask ) > > __ffs ( mask ) ;
2012-05-11 18:25:46 +04:00
}
2014-04-23 11:56:44 +04:00
/**
* ci_otg_is_fsm_mode : runtime check if otg controller
* is in otg fsm mode .
2014-09-22 04:14:17 +04:00
*
* @ ci : chipidea device
2014-04-23 11:56:44 +04:00
*/
static inline bool ci_otg_is_fsm_mode ( struct ci_hdrc * ci )
{
# ifdef CONFIG_USB_OTG_FSM
return ci - > is_otg & & ci - > roles [ CI_ROLE_HOST ] & &
ci - > roles [ CI_ROLE_GADGET ] ;
# else
return false ;
# endif
}
2014-04-23 11:56:39 +04:00
u32 hw_read_intr_enable ( struct ci_hdrc * ci ) ;
u32 hw_read_intr_status ( struct ci_hdrc * ci ) ;
2014-11-26 08:44:33 +03:00
int hw_device_reset ( struct ci_hdrc * ci ) ;
2012-05-11 18:25:46 +04:00
2013-06-24 15:46:36 +04:00
int hw_port_test_set ( struct ci_hdrc * ci , u8 mode ) ;
2012-05-11 18:25:46 +04:00
2013-06-24 15:46:36 +04:00
u8 hw_port_test_get ( struct ci_hdrc * ci ) ;
2012-05-11 18:25:46 +04:00
2013-08-14 13:44:12 +04:00
int hw_wait_reg ( struct ci_hdrc * ci , enum ci_hw_regs reg , u32 mask ,
u32 value , unsigned int timeout_ms ) ;
2012-05-11 18:25:46 +04:00
# endif /* __DRIVERS_USB_CHIPIDEA_CI_H */