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 <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <asm/io.h>
# include <linux/ioport.h>
# include <asm/pgtable.h>
# include <asm/page.h>
# include "mantis_common.h"
# define I2C_HW_B_MANTIS 0x1c
static int mantis_ack_wait ( struct mantis_pci * mantis )
{
int rc = 0 ;
2009-12-02 22:07:24 -03:00
u32 timeout = 0 ;
2009-12-02 21:57:10 -03:00
if ( wait_event_interruptible_timeout ( mantis - > i2c_wq ,
2009-12-02 22:07:24 -03:00
mantis - > mantis_int_stat & MANTIS_INT_I2CDONE ,
msecs_to_jiffies ( 50 ) ) = = - ERESTARTSYS ) {
2009-12-02 21:57:10 -03:00
2009-12-03 05:37:51 -03:00
dprintk ( verbose , MANTIS_DEBUG , 1 , " Master !I2CDONE " ) ;
2009-12-02 21:57:10 -03:00
rc = - EREMOTEIO ;
2009-12-02 22:07:24 -03:00
}
while ( ! ( mantis - > mantis_int_stat & MANTIS_INT_I2CRACK ) ) {
dprintk ( verbose , MANTIS_DEBUG , 1 , " Waiting for Slave RACK " ) ;
mantis - > mantis_int_stat = mmread ( MANTIS_INT_STAT ) ;
msleep ( 5 ) ;
timeout + + ;
if ( timeout > 500 ) {
dprintk ( verbose , MANTIS_ERROR , 1 , " Slave RACK Fail ! " ) ;
rc = - EREMOTEIO ;
2009-12-02 21:57:10 -03:00
break ;
}
}
2009-12-02 22:07:24 -03:00
udelay ( 350 ) ;
2009-12-02 21:57:10 -03:00
return rc ;
}
static int mantis_i2c_read ( struct mantis_pci * mantis , const struct i2c_msg * msg )
{
u32 rxd , i ;
2009-12-03 05:37:51 -03:00
dprintk ( verbose , MANTIS_INFO , 0 , " %s: Address=[0x%02x] <R>[ " ,
__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-02 22:07:24 -03:00
if ( mantis_ack_wait ( mantis ) ! = 0 ) {
2009-12-02 21:57:10 -03:00
dprintk ( verbose , MANTIS_DEBUG , 1 , " ACK failed<R> " ) ;
2009-12-02 22:07:24 -03:00
return - EREMOTEIO ;
2009-12-02 21:57:10 -03:00
}
rxd = mmread ( MANTIS_I2CDATA_CTL ) ;
msg - > buf [ i ] = ( u8 ) ( ( rxd > > 8 ) & 0xFF ) ;
2009-12-02 22:07:24 -03:00
dprintk ( verbose , MANTIS_INFO , 0 , " %02x " , msg - > buf [ i ] ) ;
2009-12-02 21:57:10 -03:00
}
2009-12-02 22:07:24 -03:00
dprintk ( verbose , 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 ;
u32 txd = 0 ;
2009-12-03 05:37:51 -03:00
dprintk ( verbose , MANTIS_INFO , 0 , " %s: Address=[0x%02x] <W>[ " ,
__func__ , msg - > addr ) ;
2009-12-02 21:57:10 -03:00
for ( i = 0 ; i < msg - > len ; i + + ) {
2009-12-02 22:07:24 -03:00
dprintk ( verbose , 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-02 22:07:24 -03:00
if ( mantis_ack_wait ( mantis ) ! = 0 ) {
2009-12-02 21:57:10 -03:00
dprintk ( verbose , MANTIS_DEBUG , 1 , " ACK failed<W> " ) ;
2009-12-02 22:07:24 -03:00
return - EREMOTEIO ;
2009-12-02 21:57:10 -03:00
}
}
2009-12-02 22:07:24 -03:00
dprintk ( verbose , 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 )
{
int ret = 0 , i ;
struct mantis_pci * mantis ;
mantis = i2c_get_adapdata ( adapter ) ;
2009-12-03 05:42:10 -03:00
mutex_lock ( & mantis - > i2c_lock ) ;
2009-12-02 21:57:10 -03:00
for ( i = 0 ; i < num ; i + + ) {
if ( msgs [ i ] . flags & I2C_M_RD )
ret = mantis_i2c_read ( mantis , & msgs [ i ] ) ;
else
ret = mantis_i2c_write ( mantis , & msgs [ i ] ) ;
if ( ret < 0 )
2009-12-04 04:40:16 -03:00
goto bail_out ;
2009-12-02 21:57:10 -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 ,
} ;
static struct i2c_adapter mantis_i2c_adapter = {
. owner = THIS_MODULE ,
. name = " Mantis I2C " ,
. id = I2C_HW_B_MANTIS ,
. class = I2C_CLASS_TV_DIGITAL ,
. algo = & mantis_algo ,
} ;
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-03 05:42:10 -03:00
mutex_init ( & mantis - > i2c_lock ) ;
2009-12-03 05:46:06 -03:00
memcpy ( i2c_adapter , & mantis_i2c_adapter , sizeof ( mantis_i2c_adapter ) ) ;
i2c_set_adapdata ( i2c_adapter , mantis ) ;
i2c_adapter - > dev . parent = & pdev - > dev ;
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 ;
dprintk ( verbose , MANTIS_DEBUG , 1 , " Initializing I2C .. " ) ;
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-02 22:07:24 -03:00
mmwrite ( intmask | MANTIS_INT_I2CDONE , MANTIS_INT_MASK ) ;
2009-12-02 21:57:10 -03:00
2009-12-02 22:07:24 -03:00
dprintk ( verbose , MANTIS_DEBUG , 1 , " [0x%08x/%08x] " , intstat , intmask ) ;
2009-12-02 21:57:10 -03:00
return 0 ;
}
int __devexit mantis_i2c_exit ( struct mantis_pci * mantis )
{
dprintk ( verbose , MANTIS_DEBUG , 1 , " Removing I2C adapter " ) ;
return i2c_del_adapter ( & mantis - > adapter ) ;
}