// SPDX-License-Identifier: GPL-2.0-or-later
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
*/
#include <asm /io.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <media/dmxdev.h>
#include <media/dvbdev.h>
#include <media/dvb_demux.h>
#include <media/dvb_frontend.h>
#include <media/dvb_net.h>
#include "mantis_common.h"
#include "mantis_reg.h"
#include "mantis_i2c.h"
#define TRIALS 10000
static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
{
u32 rxd, i, stat, trials;
dprintk(MANTIS_INFO, 0 , " %s: Address=[0x%02x] <R>[ " ,
__func__, msg->addr);
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;
mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
mmwrite(rxd, MANTIS_I2CDATA_CTL);
/* wait for xfer completion */
for (trials = 0 ; trials < TRIALS; trials++) {
stat = mmread(MANTIS_INT_STAT);
if (stat & MANTIS_INT_I2CDONE)
break ;
}
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);
rxd = mmread(MANTIS_I2CDATA_CTL);
msg->buf[i] = (u8)((rxd >> 8 ) & 0 xFF);
dprintk(MANTIS_INFO, 0 , "%02x " , msg->buf[i]);
}
dprintk(MANTIS_INFO, 0 , "]\n" );
return 0 ;
}
static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
{
int i;
u32 txd = 0 , stat, trials;
dprintk(MANTIS_INFO, 0 , " %s: Address=[0x%02x] <W>[ " ,
__func__, msg->addr);
for (i = 0 ; i < msg->len; i++) {
dprintk(MANTIS_INFO, 0 , "%02x " , msg->buf[i]);
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;
mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
mmwrite(txd, MANTIS_I2CDATA_CTL);
/* wait for xfer completion */
for (trials = 0 ; trials < TRIALS; trials++) {
stat = mmread(MANTIS_INT_STAT);
if (stat & MANTIS_INT_I2CDONE)
break ;
}
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);
}
dprintk(MANTIS_INFO, 0 , "]\n" );
return 0 ;
}
static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
{
int ret = 0 , i = 0 , trials;
u32 stat, data, txd;
struct mantis_pci *mantis;
struct mantis_hwconfig *config;
mantis = i2c_get_adapdata(adapter);
BUG_ON(!mantis);
config = mantis->hwconfig;
BUG_ON(!config);
dprintk(MANTIS_DEBUG, 1 , "Messages:%d" , num);
mutex_lock(&mantis->i2c_lock);
while (i < num) {
/* Byte MODE */
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)) {
dprintk(MANTIS_DEBUG, 0 , " Byte MODE:\n" );
/* Read operation */
txd = msgs[i].addr << 25 | (0 x1 << 24 )
| (msgs[i].buf[0 ] << 16 )
| MANTIS_I2C_RATE_3;
mmwrite(txd, MANTIS_I2CDATA_CTL);
/* wait for xfer completion */
for (trials = 0 ; trials < TRIALS; trials++) {
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 ) & 0 xff;
dprintk(MANTIS_DEBUG, 0 , " Byte <%d> RXD=0x%02x [%02x]\n" , 0 x0, 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;
}
}
mutex_unlock(&mantis->i2c_lock);
return num;
bail_out:
mutex_unlock(&mantis->i2c_lock);
return ret;
}
static u32 mantis_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm mantis_algo = {
.master_xfer = mantis_i2c_xfer,
.functionality = mantis_i2c_func,
};
int mantis_i2c_init(struct mantis_pci *mantis)
{
u32 intstat;
struct i2c_adapter *i2c_adapter = &mantis->adapter;
struct pci_dev *pdev = mantis->pdev;
init_waitqueue_head(&mantis->i2c_wq);
mutex_init(&mantis->i2c_lock);
strscpy(i2c_adapter->name, "Mantis I2C" , sizeof (i2c_adapter->name));
i2c_set_adapdata(i2c_adapter, mantis);
i2c_adapter->owner = THIS_MODULE;
i2c_adapter->algo = &mantis_algo;
i2c_adapter->algo_data = NULL;
i2c_adapter->timeout = 500 ;
i2c_adapter->retries = 3 ;
i2c_adapter->dev.parent = &pdev->dev;
mantis->i2c_rc = i2c_add_adapter(i2c_adapter);
if (mantis->i2c_rc < 0 )
return mantis->i2c_rc;
dprintk(MANTIS_DEBUG, 1 , "Initializing I2C .." );
intstat = mmread(MANTIS_INT_STAT);
mmread(MANTIS_INT_MASK);
mmwrite(intstat, MANTIS_INT_STAT);
dprintk(MANTIS_DEBUG, 1 , "Disabling I2C interrupt" );
mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
return 0 ;
}
EXPORT_SYMBOL_GPL(mantis_i2c_init);
int mantis_i2c_exit(struct mantis_pci *mantis)
{
dprintk(MANTIS_DEBUG, 1 , "Disabling I2C interrupt" );
mantis_mask_ints(mantis, MANTIS_INT_I2CDONE);
dprintk(MANTIS_DEBUG, 1 , "Removing I2C adapter" );
i2c_del_adapter(&mantis->adapter);
return 0 ;
}
EXPORT_SYMBOL_GPL(mantis_i2c_exit);
Messung V0.5 in Prozent C=96 H=92 G=93
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland