2019-05-27 08:55:15 +02:00
/* SPDX-License-Identifier: GPL-2.0-only */
2009-05-08 17:46:40 -04:00
/*
* Marvell 88 SE64xx / 88 SE94xx register IO interface
*
* Copyright 2007 Red Hat , Inc .
* Copyright 2008 Marvell . < kewei @ marvell . com >
2011-04-26 06:36:51 -07:00
* Copyright 2009 - 2011 Marvell . < yuxiangl @ marvell . com >
2009-05-08 17:46:40 -04:00
*/
2009-05-08 17:44:01 -04:00
# ifndef _MV_CHIPS_H_
# define _MV_CHIPS_H_
2009-05-08 17:46:40 -04:00
# define mr32(reg) readl(regs + reg)
# define mw32(reg, val) writel((val), regs + reg)
# define mw32_f(reg, val) do { \
mw32 ( reg , val ) ; \
mr32 ( reg ) ; \
} while ( 0 )
2009-05-08 17:44:01 -04:00
2009-05-08 17:46:40 -04:00
# define iow32(reg, val) outl(val, (unsigned long)(regs + reg))
# define ior32(reg) inl((unsigned long)(regs + reg))
# define iow16(reg, val) outw((unsigned long)(val, regs + reg))
# define ior16(reg) inw((unsigned long)(regs + reg))
# define iow8(reg, val) outb((unsigned long)(val, regs + reg))
# define ior8(reg) inb((unsigned long)(regs + reg))
static inline u32 mvs_cr32 ( struct mvs_info * mvi , u32 addr )
2009-05-08 17:44:01 -04:00
{
2009-05-08 17:46:40 -04:00
void __iomem * regs = mvi - > regs ;
mw32 ( MVS_CMD_ADDR , addr ) ;
return mr32 ( MVS_CMD_DATA ) ;
2009-05-08 17:44:01 -04:00
}
2009-05-08 17:46:40 -04:00
static inline void mvs_cw32 ( struct mvs_info * mvi , u32 addr , u32 val )
2009-05-08 17:44:01 -04:00
{
2009-05-08 17:46:40 -04:00
void __iomem * regs = mvi - > regs ;
mw32 ( MVS_CMD_ADDR , addr ) ;
mw32 ( MVS_CMD_DATA , val ) ;
2009-05-08 17:44:01 -04:00
}
static inline u32 mvs_read_phy_ctl ( struct mvs_info * mvi , u32 port )
{
void __iomem * regs = mvi - > regs ;
2009-05-08 17:46:40 -04:00
return ( port < 4 ) ? mr32 ( MVS_P0_SER_CTLSTAT + port * 4 ) :
mr32 ( MVS_P4_SER_CTLSTAT + ( port - 4 ) * 4 ) ;
2009-05-08 17:44:01 -04:00
}
static inline void mvs_write_phy_ctl ( struct mvs_info * mvi , u32 port , u32 val )
{
void __iomem * regs = mvi - > regs ;
if ( port < 4 )
2009-05-08 17:46:40 -04:00
mw32 ( MVS_P0_SER_CTLSTAT + port * 4 , val ) ;
2009-05-08 17:44:01 -04:00
else
2009-05-08 17:46:40 -04:00
mw32 ( MVS_P4_SER_CTLSTAT + ( port - 4 ) * 4 , val ) ;
2009-05-08 17:44:01 -04:00
}
2009-05-08 17:46:40 -04:00
static inline u32 mvs_read_port ( struct mvs_info * mvi , u32 off ,
u32 off2 , u32 port )
2009-05-08 17:44:01 -04:00
{
void __iomem * regs = mvi - > regs + off ;
void __iomem * regs2 = mvi - > regs + off2 ;
2009-05-08 17:46:40 -04:00
return ( port < 4 ) ? readl ( regs + port * 8 ) :
2009-05-08 17:44:01 -04:00
readl ( regs2 + ( port - 4 ) * 8 ) ;
}
static inline void mvs_write_port ( struct mvs_info * mvi , u32 off , u32 off2 ,
u32 port , u32 val )
{
void __iomem * regs = mvi - > regs + off ;
void __iomem * regs2 = mvi - > regs + off2 ;
if ( port < 4 )
writel ( val , regs + port * 8 ) ;
else
writel ( val , regs2 + ( port - 4 ) * 8 ) ;
}
static inline u32 mvs_read_port_cfg_data ( struct mvs_info * mvi , u32 port )
{
return mvs_read_port ( mvi , MVS_P0_CFG_DATA ,
MVS_P4_CFG_DATA , port ) ;
}
2009-05-08 17:46:40 -04:00
static inline void mvs_write_port_cfg_data ( struct mvs_info * mvi ,
u32 port , u32 val )
2009-05-08 17:44:01 -04:00
{
mvs_write_port ( mvi , MVS_P0_CFG_DATA ,
MVS_P4_CFG_DATA , port , val ) ;
}
2009-05-08 17:46:40 -04:00
static inline void mvs_write_port_cfg_addr ( struct mvs_info * mvi ,
u32 port , u32 addr )
2009-05-08 17:44:01 -04:00
{
mvs_write_port ( mvi , MVS_P0_CFG_ADDR ,
MVS_P4_CFG_ADDR , port , addr ) ;
2009-05-08 17:46:40 -04:00
mdelay ( 10 ) ;
2009-05-08 17:44:01 -04:00
}
static inline u32 mvs_read_port_vsr_data ( struct mvs_info * mvi , u32 port )
{
return mvs_read_port ( mvi , MVS_P0_VSR_DATA ,
MVS_P4_VSR_DATA , port ) ;
}
2009-05-08 17:46:40 -04:00
static inline void mvs_write_port_vsr_data ( struct mvs_info * mvi ,
u32 port , u32 val )
2009-05-08 17:44:01 -04:00
{
mvs_write_port ( mvi , MVS_P0_VSR_DATA ,
MVS_P4_VSR_DATA , port , val ) ;
}
2009-05-08 17:46:40 -04:00
static inline void mvs_write_port_vsr_addr ( struct mvs_info * mvi ,
u32 port , u32 addr )
2009-05-08 17:44:01 -04:00
{
mvs_write_port ( mvi , MVS_P0_VSR_ADDR ,
MVS_P4_VSR_ADDR , port , addr ) ;
2009-05-08 17:46:40 -04:00
mdelay ( 10 ) ;
2009-05-08 17:44:01 -04:00
}
static inline u32 mvs_read_port_irq_stat ( struct mvs_info * mvi , u32 port )
{
return mvs_read_port ( mvi , MVS_P0_INT_STAT ,
MVS_P4_INT_STAT , port ) ;
}
2009-05-08 17:46:40 -04:00
static inline void mvs_write_port_irq_stat ( struct mvs_info * mvi ,
u32 port , u32 val )
2009-05-08 17:44:01 -04:00
{
mvs_write_port ( mvi , MVS_P0_INT_STAT ,
MVS_P4_INT_STAT , port , val ) ;
}
static inline u32 mvs_read_port_irq_mask ( struct mvs_info * mvi , u32 port )
{
return mvs_read_port ( mvi , MVS_P0_INT_MASK ,
MVS_P4_INT_MASK , port ) ;
2009-05-08 17:46:40 -04:00
2009-05-08 17:44:01 -04:00
}
2009-05-08 17:46:40 -04:00
static inline void mvs_write_port_irq_mask ( struct mvs_info * mvi ,
u32 port , u32 val )
2009-05-08 17:44:01 -04:00
{
mvs_write_port ( mvi , MVS_P0_INT_MASK ,
MVS_P4_INT_MASK , port , val ) ;
}
2012-12-21 13:08:55 -08:00
static inline void mvs_phy_hacks ( struct mvs_info * mvi )
2009-05-08 17:46:40 -04:00
{
u32 tmp ;
tmp = mvs_cr32 ( mvi , CMD_PHY_TIMER ) ;
tmp & = ~ ( 1 < < 9 ) ;
tmp | = ( 1 < < 10 ) ;
mvs_cw32 ( mvi , CMD_PHY_TIMER , tmp ) ;
/* enable retry 127 times */
mvs_cw32 ( mvi , CMD_SAS_CTL1 , 0x7f7f ) ;
/* extend open frame timeout to max */
tmp = mvs_cr32 ( mvi , CMD_SAS_CTL0 ) ;
tmp & = ~ 0xffff ;
tmp | = 0x3fff ;
mvs_cw32 ( mvi , CMD_SAS_CTL0 , tmp ) ;
mvs_cw32 ( mvi , CMD_WD_TIMER , 0x7a0000 ) ;
/* not to halt for different port op during wideport link change */
mvs_cw32 ( mvi , CMD_APP_ERR_CONFIG , 0xffefbf7d ) ;
}
static inline void mvs_int_sata ( struct mvs_info * mvi )
{
u32 tmp ;
void __iomem * regs = mvi - > regs ;
tmp = mr32 ( MVS_INT_STAT_SRS_0 ) ;
if ( tmp )
mw32 ( MVS_INT_STAT_SRS_0 , tmp ) ;
MVS_CHIP_DISP - > clear_active_cmds ( mvi ) ;
}
static inline void mvs_int_full ( struct mvs_info * mvi )
{
void __iomem * regs = mvi - > regs ;
u32 tmp , stat ;
int i ;
stat = mr32 ( MVS_INT_STAT ) ;
mvs_int_rx ( mvi , false ) ;
for ( i = 0 ; i < mvi - > chip - > n_phy ; i + + ) {
tmp = ( stat > > i ) & ( CINT_PORT | CINT_PORT_STOPPED ) ;
if ( tmp )
mvs_int_port ( mvi , i , tmp ) ;
}
2011-05-24 22:26:50 +08:00
if ( stat & CINT_NON_SPEC_NCQ_ERROR )
MVS_CHIP_DISP - > non_spec_ncq_error ( mvi ) ;
2009-05-08 17:46:40 -04:00
if ( stat & CINT_SRS )
mvs_int_sata ( mvi ) ;
mw32 ( MVS_INT_STAT , stat ) ;
}
static inline void mvs_start_delivery ( struct mvs_info * mvi , u32 tx )
{
void __iomem * regs = mvi - > regs ;
mw32 ( MVS_TX_PROD_IDX , tx ) ;
}
static inline u32 mvs_rx_update ( struct mvs_info * mvi )
{
void __iomem * regs = mvi - > regs ;
return mr32 ( MVS_RX_CONS_IDX ) ;
}
static inline u32 mvs_get_prd_size ( void )
{
return sizeof ( struct mvs_prd ) ;
}
static inline u32 mvs_get_prd_count ( void )
{
return MAX_SG_ENTRY ;
}
static inline void mvs_show_pcie_usage ( struct mvs_info * mvi )
{
u16 link_stat , link_spd ;
const char * spd [ ] = {
" UnKnown " ,
" 2.5 " ,
" 5.0 " ,
} ;
if ( mvi - > flags & MVF_FLAG_SOC | | mvi - > id > 0 )
return ;
pci_read_config_word ( mvi - > pdev , PCR_LINK_STAT , & link_stat ) ;
link_spd = ( link_stat & PLS_LINK_SPD ) > > PLS_LINK_SPD_OFFS ;
if ( link_spd > = 3 )
link_spd = 0 ;
dev_printk ( KERN_INFO , mvi - > dev ,
" mvsas: PCI-E x%u, Bandwidth Usage: %s Gbps \n " ,
( link_stat & PLS_NEG_LINK_WD ) > > PLS_NEG_LINK_WD_OFFS ,
spd [ link_spd ] ) ;
}
static inline u32 mvs_hw_max_link_rate ( void )
{
return MAX_LINK_RATE ;
}
# endif /* _MV_CHIPS_H_ */