2009-12-02 21:57:10 -03:00
/*
Mantis PCI bridge driver
Copyright ( C ) 2005 , 2006 Manu Abraham ( abraham . manu @ gmail . com )
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <asm/io.h>
# include <linux/ioport.h>
2009-12-04 05:41:11 -03:00
# include <linux/pci.h>
# include <linux/i2c.h>
# include "dmxdev.h"
# include "dvbdev.h"
# include "dvb_demux.h"
# include "dvb_frontend.h"
# include "dvb_net.h"
2009-12-02 21:57:10 -03:00
# include "mantis_common.h"
2009-12-04 05:41:11 -03:00
# include "mantis_reg.h"
# include "mantis_i2c.h"
2009-12-02 21:57:10 -03:00
2009-12-04 05:57:28 -03:00
# define TRIALS 10000
2009-12-02 21:57:10 -03:00
static int mantis_i2c_read ( struct mantis_pci * mantis , const struct i2c_msg * msg )
{
2009-12-04 05:56:35 -03:00
u32 rxd , i , stat , trials ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_INFO , 0 , " %s: Address=[0x%02x] <R>[ " ,
2009-12-03 05:37:51 -03:00
__func__ , msg - > addr ) ;
2009-12-02 21:57:10 -03:00
for ( i = 0 ; i < msg - > len ; i + + ) {
rxd = ( msg - > addr < < 25 ) | ( 1 < < 24 )
| MANTIS_I2C_RATE_3
| MANTIS_I2C_STOP
| MANTIS_I2C_PGMODE ;
if ( i = = ( msg - > len - 1 ) )
rxd & = ~ MANTIS_I2C_STOP ;
2009-12-02 22:07:24 -03:00
mmwrite ( MANTIS_INT_I2CDONE , MANTIS_INT_STAT ) ;
2009-12-02 21:57:10 -03:00
mmwrite ( rxd , MANTIS_I2CDATA_CTL ) ;
2009-12-04 05:56:35 -03:00
/* wait for xfer completion */
2009-12-04 05:57:28 -03:00
for ( trials = 0 ; trials < TRIALS ; trials + + ) {
2009-12-04 05:56:35 -03:00
stat = mmread ( MANTIS_INT_STAT ) ;
if ( stat & MANTIS_INT_I2CDONE )
break ;
2009-12-02 21:57:10 -03:00
}
2009-12-04 05:56:35 -03:00
2009-12-04 05:57:28 -03:00
dprintk ( MANTIS_TMG , 0 , " I2CDONE: trials=%d \n " , trials ) ;
/* wait for xfer completion */
for ( trials = 0 ; trials < TRIALS ; trials + + ) {
stat = mmread ( MANTIS_INT_STAT ) ;
if ( stat & MANTIS_INT_I2CRACK )
break ;
}
dprintk ( MANTIS_TMG , 0 , " I2CRACK: trials=%d \n " , trials ) ;
2009-12-02 21:57:10 -03:00
rxd = mmread ( MANTIS_I2CDATA_CTL ) ;
msg - > buf [ i ] = ( u8 ) ( ( rxd > > 8 ) & 0xFF ) ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_INFO , 0 , " %02x " , msg - > buf [ i ] ) ;
2009-12-02 21:57:10 -03:00
}
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_INFO , 0 , " ] \n " ) ;
2009-12-02 21:57:10 -03:00
return 0 ;
}
static int mantis_i2c_write ( struct mantis_pci * mantis , const struct i2c_msg * msg )
{
int i ;
2009-12-04 05:56:35 -03:00
u32 txd = 0 , stat , trials ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_INFO , 0 , " %s: Address=[0x%02x] <W>[ " ,
2009-12-03 05:37:51 -03:00
__func__ , msg - > addr ) ;
2009-12-02 21:57:10 -03:00
for ( i = 0 ; i < msg - > len ; i + + ) {
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_INFO , 0 , " %02x " , msg - > buf [ i ] ) ;
2009-12-02 21:57:10 -03:00
txd = ( msg - > addr < < 25 ) | ( msg - > buf [ i ] < < 8 )
| MANTIS_I2C_RATE_3
| MANTIS_I2C_STOP
| MANTIS_I2C_PGMODE ;
if ( i = = ( msg - > len - 1 ) )
txd & = ~ MANTIS_I2C_STOP ;
2009-12-02 22:07:24 -03:00
mmwrite ( MANTIS_INT_I2CDONE , MANTIS_INT_STAT ) ;
2009-12-02 21:57:10 -03:00
mmwrite ( txd , MANTIS_I2CDATA_CTL ) ;
2009-12-04 05:56:35 -03:00
/* wait for xfer completion */
2009-12-04 05:57:28 -03:00
for ( trials = 0 ; trials < TRIALS ; trials + + ) {
2009-12-04 05:56:35 -03:00
stat = mmread ( MANTIS_INT_STAT ) ;
if ( stat & MANTIS_INT_I2CDONE )
break ;
2009-12-02 21:57:10 -03:00
}
2009-12-04 05:57:28 -03:00
dprintk ( MANTIS_TMG , 0 , " I2CDONE: trials=%d \n " , trials ) ;
/* wait for xfer completion */
for ( trials = 0 ; trials < TRIALS ; trials + + ) {
stat = mmread ( MANTIS_INT_STAT ) ;
if ( stat & MANTIS_INT_I2CRACK )
break ;
}
dprintk ( MANTIS_TMG , 0 , " I2CRACK: trials=%d \n " , trials ) ;
2009-12-02 21:57:10 -03:00
}
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_INFO , 0 , " ] \n " ) ;
2009-12-02 21:57:10 -03:00
return 0 ;
}
static int mantis_i2c_xfer ( struct i2c_adapter * adapter , struct i2c_msg * msgs , int num )
{
2009-12-04 05:56:35 -03:00
int ret = 0 , i = 0 , trials ;
u32 stat , data , txd ;
2009-12-02 21:57:10 -03:00
struct mantis_pci * mantis ;
2009-12-04 05:56:35 -03:00
struct mantis_hwconfig * config ;
2009-12-02 21:57:10 -03:00
mantis = i2c_get_adapdata ( adapter ) ;
2009-12-04 05:56:35 -03:00
BUG_ON ( ! mantis ) ;
config = mantis - > hwconfig ;
BUG_ON ( ! config ) ;
dprintk ( MANTIS_DEBUG , 1 , " Messages:%d " , num ) ;
2009-12-03 05:42:10 -03:00
mutex_lock ( & mantis - > i2c_lock ) ;
2009-12-04 05:56:35 -03:00
while ( i < num ) {
/* Byte MODE */
2009-12-04 05:57:28 -03:00
if ( ( config - > i2c_mode & MANTIS_BYTE_MODE ) & &
( ( i + 1 ) < num ) & &
( msgs [ i ] . len < 2 ) & &
( msgs [ i + 1 ] . len < 2 ) & &
( msgs [ i + 1 ] . flags & I2C_M_RD ) ) {
2009-12-04 05:56:35 -03:00
dprintk ( MANTIS_DEBUG , 0 , " Byte MODE: \n " ) ;
/* Read operation */
txd = msgs [ i ] . addr < < 25 | ( 0x1 < < 24 )
| ( msgs [ i ] . buf [ 0 ] < < 16 )
| MANTIS_I2C_RATE_3 ;
mmwrite ( txd , MANTIS_I2CDATA_CTL ) ;
/* wait for xfer completion */
2009-12-04 05:57:28 -03:00
for ( trials = 0 ; trials < TRIALS ; trials + + ) {
2009-12-04 05:56:35 -03:00
stat = mmread ( MANTIS_INT_STAT ) ;
if ( stat & MANTIS_INT_I2CDONE )
break ;
}
/* check for xfer completion */
if ( stat & MANTIS_INT_I2CDONE ) {
/* check xfer was acknowledged */
if ( stat & MANTIS_INT_I2CRACK ) {
data = mmread ( MANTIS_I2CDATA_CTL ) ;
msgs [ i + 1 ] . buf [ 0 ] = ( data > > 8 ) & 0xff ;
dprintk ( MANTIS_DEBUG , 0 , " Byte <%d> RXD=0x%02x [%02x] \n " , 0x0 , data , msgs [ i + 1 ] . buf [ 0 ] ) ;
} else {
/* I/O error */
dprintk ( MANTIS_ERROR , 1 , " I/O error, LINE:%d " , __LINE__ ) ;
ret = - EIO ;
break ;
}
} else {
/* I/O error */
dprintk ( MANTIS_ERROR , 1 , " I/O error, LINE:%d " , __LINE__ ) ;
ret = - EIO ;
break ;
}
i + = 2 ; /* Write/Read operation in one go */
}
if ( i < num ) {
if ( msgs [ i ] . flags & I2C_M_RD )
ret = mantis_i2c_read ( mantis , & msgs [ i ] ) ;
else
ret = mantis_i2c_write ( mantis , & msgs [ i ] ) ;
i + + ;
if ( ret < 0 )
goto bail_out ;
}
2009-12-02 21:57:10 -03:00
}
2009-12-04 05:56:35 -03:00
2009-12-03 05:42:10 -03:00
mutex_unlock ( & mantis - > i2c_lock ) ;
2009-12-02 21:57:10 -03:00
return num ;
2009-12-04 04:40:16 -03:00
bail_out :
mutex_unlock ( & mantis - > i2c_lock ) ;
return ret ;
2009-12-02 21:57:10 -03:00
}
static u32 mantis_i2c_func ( struct i2c_adapter * adapter )
{
return I2C_FUNC_SMBUS_EMUL ;
}
static struct i2c_algorithm mantis_algo = {
. master_xfer = mantis_i2c_xfer ,
. functionality = mantis_i2c_func ,
} ;
int __devinit mantis_i2c_init ( struct mantis_pci * mantis )
{
2009-12-02 22:07:24 -03:00
u32 intstat , intmask ;
2009-12-03 05:46:06 -03:00
struct i2c_adapter * i2c_adapter = & mantis - > adapter ;
struct pci_dev * pdev = mantis - > pdev ;
2009-12-02 21:57:10 -03:00
2009-12-04 05:41:11 -03:00
init_waitqueue_head ( & mantis - > i2c_wq ) ;
2009-12-03 05:42:10 -03:00
mutex_init ( & mantis - > i2c_lock ) ;
2009-12-15 08:47:21 -03:00
strncpy ( i2c_adapter - > name , " Mantis I2C " , sizeof ( i2c_adapter - > name ) ) ;
2009-12-03 05:46:06 -03:00
i2c_set_adapdata ( i2c_adapter , mantis ) ;
2009-12-04 05:41:11 -03:00
i2c_adapter - > owner = THIS_MODULE ;
i2c_adapter - > class = I2C_CLASS_TV_DIGITAL ;
i2c_adapter - > algo = & mantis_algo ;
i2c_adapter - > algo_data = NULL ;
i2c_adapter - > timeout = 500 ;
i2c_adapter - > retries = 3 ;
i2c_adapter - > dev . parent = & pdev - > dev ;
2009-12-03 05:46:06 -03:00
mantis - > i2c_rc = i2c_add_adapter ( i2c_adapter ) ;
2009-12-02 21:57:10 -03:00
if ( mantis - > i2c_rc < 0 )
return mantis - > i2c_rc ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " Initializing I2C .. " ) ;
2009-12-02 21:57:10 -03:00
intstat = mmread ( MANTIS_INT_STAT ) ;
2009-12-02 22:07:24 -03:00
intmask = mmread ( MANTIS_INT_MASK ) ;
2009-12-02 21:57:10 -03:00
mmwrite ( intstat , MANTIS_INT_STAT ) ;
2009-12-04 05:56:35 -03:00
dprintk ( MANTIS_DEBUG , 1 , " Disabling I2C interrupt " ) ;
intmask = mmread ( MANTIS_INT_MASK ) ;
mmwrite ( ( intmask & ~ MANTIS_INT_I2CDONE ) , MANTIS_INT_MASK ) ;
2009-12-02 21:57:10 -03:00
return 0 ;
}
2009-12-04 05:41:11 -03:00
EXPORT_SYMBOL_GPL ( mantis_i2c_init ) ;
2009-12-02 21:57:10 -03:00
int __devexit mantis_i2c_exit ( struct mantis_pci * mantis )
{
2009-12-04 05:56:35 -03:00
u32 intmask ;
dprintk ( MANTIS_DEBUG , 1 , " Disabling I2C interrupt " ) ;
intmask = mmread ( MANTIS_INT_MASK ) ;
mmwrite ( ( intmask & ~ MANTIS_INT_I2CDONE ) , MANTIS_INT_MASK ) ;
2009-12-04 05:41:11 -03:00
dprintk ( MANTIS_DEBUG , 1 , " Removing I2C adapter " ) ;
2009-12-02 21:57:10 -03:00
return i2c_del_adapter ( & mantis - > adapter ) ;
}
2009-12-04 05:41:11 -03:00
EXPORT_SYMBOL_GPL ( mantis_i2c_exit ) ;