2017-11-03 13:28:30 +03:00
// SPDX-License-Identifier: GPL-2.0
2007-05-10 08:18:19 +04:00
/*
* R8A66597 HCD ( Host Controller Driver )
*
* Copyright ( C ) 2006 - 2007 Renesas Solutions Corp .
* Portions Copyright ( C ) 2004 Psion Teklogix ( for NetBook PRO )
* Portions Copyright ( C ) 2004 - 2005 David Brownell
* Portions Copyright ( C ) 1999 Roman Weissgaerber
*
* Author : Yoshihiro Shimoda < shimoda . yoshihiro @ renesas . com >
*/
# ifndef __R8A66597_H__
# define __R8A66597_H__
2008-10-31 14:22:38 +03:00
# include <linux/clk.h>
2009-05-26 13:24:34 +04:00
# include <linux/usb/r8a66597.h>
2007-05-10 08:18:19 +04:00
# define R8A66597_MAX_NUM_PIPE 10
# define R8A66597_BUF_BSIZE 8
# define R8A66597_MAX_DEVICE 10
# define R8A66597_MAX_ROOT_HUB 2
2008-04-10 16:05:55 +04:00
# define R8A66597_MAX_SAMPLING 5
# define R8A66597_RH_POLL_TIME 10
2007-05-10 08:18:19 +04:00
# define R8A66597_MAX_DMA_CHANNEL 2
# define R8A66597_PIPE_NO_DMA R8A66597_MAX_DMA_CHANNEL
# define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5))
# define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9))
# define make_devsel(addr) (addr << 12)
struct r8a66597_pipe_info {
2008-04-10 16:05:47 +04:00
unsigned long timer_interval ;
2007-07-18 18:10:34 +04:00
u16 pipenum ;
2007-12-17 22:40:18 +03:00
u16 address ; /* R8A66597 HCD usb address */
2007-07-18 18:10:34 +04:00
u16 epnum ;
u16 maxpacket ;
u16 type ;
u16 bufnum ;
u16 buf_bsize ;
u16 interval ;
u16 dir_in ;
2007-05-10 08:18:19 +04:00
} ;
struct r8a66597_pipe {
struct r8a66597_pipe_info info ;
unsigned long fifoaddr ;
unsigned long fifosel ;
unsigned long fifoctr ;
unsigned long pipectr ;
unsigned long pipetre ;
unsigned long pipetrn ;
} ;
struct r8a66597_td {
struct r8a66597_pipe * pipe ;
struct urb * urb ;
struct list_head queue ;
u16 type ;
u16 pipenum ;
int iso_cnt ;
u16 address ; /* R8A66597's USB address */
u16 maxpacket ;
unsigned zero_packet : 1 ;
unsigned short_packet : 1 ;
unsigned set_address : 1 ;
} ;
struct r8a66597_device {
u16 address ; /* R8A66597's USB address */
u16 hub_port ;
u16 root_port ;
unsigned short ep_in_toggle ;
unsigned short ep_out_toggle ;
unsigned char pipe_cnt [ R8A66597_MAX_NUM_PIPE ] ;
unsigned char dma_map ;
enum usb_device_state state ;
struct usb_device * udev ;
int usb_address ;
struct list_head device_list ;
} ;
struct r8a66597_root_hub {
u32 port ;
u16 old_syssts ;
int scount ;
struct r8a66597_device * dev ;
} ;
2017-10-24 13:08:42 +03:00
struct r8a66597 ;
struct r8a66597_timers {
struct timer_list td ;
struct timer_list interval ;
struct r8a66597 * r8a66597 ;
} ;
2007-05-10 08:18:19 +04:00
struct r8a66597 {
spinlock_t lock ;
2010-06-02 11:27:54 +04:00
void __iomem * reg ;
2008-10-31 14:22:38 +03:00
struct clk * clk ;
2009-05-26 13:24:34 +04:00
struct r8a66597_platdata * pdata ;
2007-05-10 08:18:19 +04:00
struct r8a66597_device device0 ;
struct r8a66597_root_hub root_hub [ R8A66597_MAX_ROOT_HUB ] ;
struct list_head pipe_queue [ R8A66597_MAX_NUM_PIPE ] ;
struct timer_list rh_timer ;
2017-10-24 13:08:42 +03:00
struct r8a66597_timers timers [ R8A66597_MAX_NUM_PIPE ] ;
2007-05-10 08:18:19 +04:00
unsigned short address_map ;
unsigned short timeout_map ;
2008-04-10 16:05:47 +04:00
unsigned short interval_map ;
2007-05-10 08:18:19 +04:00
unsigned char pipe_cnt [ R8A66597_MAX_NUM_PIPE ] ;
unsigned char dma_map ;
2009-07-17 18:59:55 +04:00
unsigned int max_root_hub ;
2007-05-10 08:18:19 +04:00
struct list_head child_device ;
unsigned long child_connect_map [ 4 ] ;
2009-03-19 08:18:15 +03:00
unsigned bus_suspended : 1 ;
2009-05-26 13:24:34 +04:00
unsigned irq_sense_low : 1 ;
2007-05-10 08:18:19 +04:00
} ;
static inline struct r8a66597 * hcd_to_r8a66597 ( struct usb_hcd * hcd )
{
return ( struct r8a66597 * ) ( hcd - > hcd_priv ) ;
}
static inline struct usb_hcd * r8a66597_to_hcd ( struct r8a66597 * r8a66597 )
{
return container_of ( ( void * ) r8a66597 , struct usb_hcd , hcd_priv ) ;
}
static inline struct r8a66597_td * r8a66597_get_td ( struct r8a66597 * r8a66597 ,
u16 pipenum )
{
if ( unlikely ( list_empty ( & r8a66597 - > pipe_queue [ pipenum ] ) ) )
return NULL ;
return list_entry ( r8a66597 - > pipe_queue [ pipenum ] . next ,
struct r8a66597_td , queue ) ;
}
static inline struct urb * r8a66597_get_urb ( struct r8a66597 * r8a66597 ,
u16 pipenum )
{
struct r8a66597_td * td ;
td = r8a66597_get_td ( r8a66597 , pipenum ) ;
return ( td ? td - > urb : NULL ) ;
}
static inline u16 r8a66597_read ( struct r8a66597 * r8a66597 , unsigned long offset )
{
2010-06-02 11:27:54 +04:00
return ioread16 ( r8a66597 - > reg + offset ) ;
2007-05-10 08:18:19 +04:00
}
static inline void r8a66597_read_fifo ( struct r8a66597 * r8a66597 ,
unsigned long offset , u16 * buf ,
int len )
{
2010-06-02 11:27:54 +04:00
void __iomem * fifoaddr = r8a66597 - > reg + offset ;
2008-04-10 16:05:58 +04:00
unsigned long count ;
2009-07-17 18:59:55 +04:00
if ( r8a66597 - > pdata - > on_chip ) {
count = len / 4 ;
2010-06-02 11:27:54 +04:00
ioread32_rep ( fifoaddr , buf , count ) ;
2008-04-10 16:05:58 +04:00
2009-07-17 18:59:55 +04:00
if ( len & 0x00000003 ) {
2010-06-02 11:27:54 +04:00
unsigned long tmp = ioread32 ( fifoaddr ) ;
2009-07-17 18:59:55 +04:00
memcpy ( ( unsigned char * ) buf + count * 4 , & tmp ,
len & 0x03 ) ;
}
} else {
len = ( len + 1 ) / 2 ;
2010-06-02 11:27:54 +04:00
ioread16_rep ( fifoaddr , buf , len ) ;
2008-04-10 16:05:58 +04:00
}
2007-05-10 08:18:19 +04:00
}
static inline void r8a66597_write ( struct r8a66597 * r8a66597 , u16 val ,
unsigned long offset )
{
2010-06-02 11:27:54 +04:00
iowrite16 ( val , r8a66597 - > reg + offset ) ;
2007-05-10 08:18:19 +04:00
}
2011-07-07 04:57:10 +04:00
static inline void r8a66597_mdfy ( struct r8a66597 * r8a66597 ,
u16 val , u16 pat , unsigned long offset )
{
u16 tmp ;
tmp = r8a66597_read ( r8a66597 , offset ) ;
tmp = tmp & ( ~ pat ) ;
tmp = tmp | val ;
r8a66597_write ( r8a66597 , tmp , offset ) ;
}
# define r8a66597_bclr(r8a66597, val, offset) \
r8a66597_mdfy ( r8a66597 , 0 , val , offset )
# define r8a66597_bset(r8a66597, val, offset) \
r8a66597_mdfy ( r8a66597 , val , 0 , offset )
2007-05-10 08:18:19 +04:00
static inline void r8a66597_write_fifo ( struct r8a66597 * r8a66597 ,
2011-07-07 04:57:10 +04:00
struct r8a66597_pipe * pipe , u16 * buf ,
2007-05-10 08:18:19 +04:00
int len )
{
2011-07-07 04:57:10 +04:00
void __iomem * fifoaddr = r8a66597 - > reg + pipe - > fifoaddr ;
2008-04-10 16:05:58 +04:00
unsigned long count ;
unsigned char * pb ;
int i ;
2009-07-17 18:59:55 +04:00
if ( r8a66597 - > pdata - > on_chip ) {
count = len / 4 ;
2010-06-02 11:27:54 +04:00
iowrite32_rep ( fifoaddr , buf , count ) ;
2009-07-17 18:59:55 +04:00
if ( len & 0x00000003 ) {
pb = ( unsigned char * ) buf + count * 4 ;
for ( i = 0 ; i < ( len & 0x00000003 ) ; i + + ) {
if ( r8a66597_read ( r8a66597 , CFIFOSEL ) & BIGEND )
2010-06-02 11:27:54 +04:00
iowrite8 ( pb [ i ] , fifoaddr + i ) ;
2009-07-17 18:59:55 +04:00
else
2010-06-02 11:27:54 +04:00
iowrite8 ( pb [ i ] , fifoaddr + 3 - i ) ;
2009-07-17 18:59:55 +04:00
}
}
} else {
int odd = len & 0x0001 ;
len = len / 2 ;
2010-10-14 09:52:54 +04:00
iowrite16_rep ( fifoaddr , buf , len ) ;
2009-07-17 18:59:55 +04:00
if ( unlikely ( odd ) ) {
buf = & buf [ len ] ;
2011-07-07 04:57:10 +04:00
if ( r8a66597 - > pdata - > wr0_shorted_to_wr1 )
r8a66597_bclr ( r8a66597 , MBW_16 , pipe - > fifosel ) ;
2010-06-02 11:27:54 +04:00
iowrite8 ( ( unsigned char ) * buf , fifoaddr ) ;
2011-07-07 04:57:10 +04:00
if ( r8a66597 - > pdata - > wr0_shorted_to_wr1 )
r8a66597_bset ( r8a66597 , MBW_16 , pipe - > fifosel ) ;
2008-04-10 16:05:58 +04:00
}
}
2007-05-10 08:18:19 +04:00
}
static inline unsigned long get_syscfg_reg ( int port )
{
return port = = 0 ? SYSCFG0 : SYSCFG1 ;
}
static inline unsigned long get_syssts_reg ( int port )
{
return port = = 0 ? SYSSTS0 : SYSSTS1 ;
}
static inline unsigned long get_dvstctr_reg ( int port )
{
return port = = 0 ? DVSTCTR0 : DVSTCTR1 ;
}
2008-04-10 16:05:58 +04:00
static inline unsigned long get_dmacfg_reg ( int port )
{
return port = = 0 ? DMA0CFG : DMA1CFG ;
}
2007-05-10 08:18:19 +04:00
static inline unsigned long get_intenb_reg ( int port )
{
return port = = 0 ? INTENB1 : INTENB2 ;
}
static inline unsigned long get_intsts_reg ( int port )
{
return port = = 0 ? INTSTS1 : INTSTS2 ;
}
static inline u16 get_rh_usb_speed ( struct r8a66597 * r8a66597 , int port )
{
unsigned long dvstctr_reg = get_dvstctr_reg ( port ) ;
return r8a66597_read ( r8a66597 , dvstctr_reg ) & RHST ;
}
static inline void r8a66597_port_power ( struct r8a66597 * r8a66597 , int port ,
int power )
{
unsigned long dvstctr_reg = get_dvstctr_reg ( port ) ;
2009-05-26 13:24:34 +04:00
if ( r8a66597 - > pdata - > port_power ) {
r8a66597 - > pdata - > port_power ( port , power ) ;
} else {
if ( power )
r8a66597_bset ( r8a66597 , VBOUT , dvstctr_reg ) ;
else
r8a66597_bclr ( r8a66597 , VBOUT , dvstctr_reg ) ;
}
}
static inline u16 get_xtal_from_pdata ( struct r8a66597_platdata * pdata )
{
u16 clock = 0 ;
switch ( pdata - > xtal ) {
case R8A66597_PLATDATA_XTAL_12MHZ :
clock = XTAL12 ;
break ;
case R8A66597_PLATDATA_XTAL_24MHZ :
clock = XTAL24 ;
break ;
case R8A66597_PLATDATA_XTAL_48MHZ :
clock = XTAL48 ;
break ;
default :
printk ( KERN_ERR " r8a66597: platdata clock is wrong. \n " ) ;
break ;
}
return clock ;
2007-05-10 08:18:19 +04:00
}
# define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2)
# define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4)
# define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4)
# define get_devadd_addr(address) (DEVADD0 + address * 2)
# define enable_irq_ready(r8a66597, pipenum) \
enable_pipe_irq ( r8a66597 , pipenum , BRDYENB )
# define disable_irq_ready(r8a66597, pipenum) \
disable_pipe_irq ( r8a66597 , pipenum , BRDYENB )
# define enable_irq_empty(r8a66597, pipenum) \
enable_pipe_irq ( r8a66597 , pipenum , BEMPENB )
# define disable_irq_empty(r8a66597, pipenum) \
disable_pipe_irq ( r8a66597 , pipenum , BEMPENB )
# define enable_irq_nrdy(r8a66597, pipenum) \
enable_pipe_irq ( r8a66597 , pipenum , NRDYENB )
# define disable_irq_nrdy(r8a66597, pipenum) \
disable_pipe_irq ( r8a66597 , pipenum , NRDYENB )
# endif /* __R8A66597_H__ */