Path: blob/master/drivers/media/dvb/mantis/mantis_i2c.c
15112 views
/*1Mantis PCI bridge driver23Copyright (C) Manu Abraham ([email protected])45This program is free software; you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation; either version 2 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program; if not, write to the Free Software17Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.18*/1920#include <asm/io.h>21#include <linux/ioport.h>22#include <linux/pci.h>23#include <linux/i2c.h>2425#include "dmxdev.h"26#include "dvbdev.h"27#include "dvb_demux.h"28#include "dvb_frontend.h"29#include "dvb_net.h"3031#include "mantis_common.h"32#include "mantis_reg.h"33#include "mantis_i2c.h"3435#define TRIALS 100003637static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)38{39u32 rxd, i, stat, trials;4041dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] <R>[ ",42__func__, msg->addr);4344for (i = 0; i < msg->len; i++) {45rxd = (msg->addr << 25) | (1 << 24)46| MANTIS_I2C_RATE_347| MANTIS_I2C_STOP48| MANTIS_I2C_PGMODE;4950if (i == (msg->len - 1))51rxd &= ~MANTIS_I2C_STOP;5253mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);54mmwrite(rxd, MANTIS_I2CDATA_CTL);5556/* wait for xfer completion */57for (trials = 0; trials < TRIALS; trials++) {58stat = mmread(MANTIS_INT_STAT);59if (stat & MANTIS_INT_I2CDONE)60break;61}6263dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);6465/* wait for xfer completion */66for (trials = 0; trials < TRIALS; trials++) {67stat = mmread(MANTIS_INT_STAT);68if (stat & MANTIS_INT_I2CRACK)69break;70}7172dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);7374rxd = mmread(MANTIS_I2CDATA_CTL);75msg->buf[i] = (u8)((rxd >> 8) & 0xFF);76dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);77}78dprintk(MANTIS_INFO, 0, "]\n");7980return 0;81}8283static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)84{85int i;86u32 txd = 0, stat, trials;8788dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] <W>[ ",89__func__, msg->addr);9091for (i = 0; i < msg->len; i++) {92dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);93txd = (msg->addr << 25) | (msg->buf[i] << 8)94| MANTIS_I2C_RATE_395| MANTIS_I2C_STOP96| MANTIS_I2C_PGMODE;9798if (i == (msg->len - 1))99txd &= ~MANTIS_I2C_STOP;100101mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);102mmwrite(txd, MANTIS_I2CDATA_CTL);103104/* wait for xfer completion */105for (trials = 0; trials < TRIALS; trials++) {106stat = mmread(MANTIS_INT_STAT);107if (stat & MANTIS_INT_I2CDONE)108break;109}110111dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);112113/* wait for xfer completion */114for (trials = 0; trials < TRIALS; trials++) {115stat = mmread(MANTIS_INT_STAT);116if (stat & MANTIS_INT_I2CRACK)117break;118}119120dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);121}122dprintk(MANTIS_INFO, 0, "]\n");123124return 0;125}126127static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)128{129int ret = 0, i = 0, trials;130u32 stat, data, txd;131struct mantis_pci *mantis;132struct mantis_hwconfig *config;133134mantis = i2c_get_adapdata(adapter);135BUG_ON(!mantis);136config = mantis->hwconfig;137BUG_ON(!config);138139dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);140mutex_lock(&mantis->i2c_lock);141142while (i < num) {143/* Byte MODE */144if ((config->i2c_mode & MANTIS_BYTE_MODE) &&145((i + 1) < num) &&146(msgs[i].len < 2) &&147(msgs[i + 1].len < 2) &&148(msgs[i + 1].flags & I2C_M_RD)) {149150dprintk(MANTIS_DEBUG, 0, " Byte MODE:\n");151152/* Read operation */153txd = msgs[i].addr << 25 | (0x1 << 24)154| (msgs[i].buf[0] << 16)155| MANTIS_I2C_RATE_3;156157mmwrite(txd, MANTIS_I2CDATA_CTL);158/* wait for xfer completion */159for (trials = 0; trials < TRIALS; trials++) {160stat = mmread(MANTIS_INT_STAT);161if (stat & MANTIS_INT_I2CDONE)162break;163}164165/* check for xfer completion */166if (stat & MANTIS_INT_I2CDONE) {167/* check xfer was acknowledged */168if (stat & MANTIS_INT_I2CRACK) {169data = mmread(MANTIS_I2CDATA_CTL);170msgs[i + 1].buf[0] = (data >> 8) & 0xff;171dprintk(MANTIS_DEBUG, 0, " Byte <%d> RXD=0x%02x [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);172} else {173/* I/O error */174dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__);175ret = -EIO;176break;177}178} else {179/* I/O error */180dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__);181ret = -EIO;182break;183}184i += 2; /* Write/Read operation in one go */185}186187if (i < num) {188if (msgs[i].flags & I2C_M_RD)189ret = mantis_i2c_read(mantis, &msgs[i]);190else191ret = mantis_i2c_write(mantis, &msgs[i]);192193i++;194if (ret < 0)195goto bail_out;196}197198}199200mutex_unlock(&mantis->i2c_lock);201202return num;203204bail_out:205mutex_unlock(&mantis->i2c_lock);206return ret;207}208209static u32 mantis_i2c_func(struct i2c_adapter *adapter)210{211return I2C_FUNC_SMBUS_EMUL;212}213214static struct i2c_algorithm mantis_algo = {215.master_xfer = mantis_i2c_xfer,216.functionality = mantis_i2c_func,217};218219int __devinit mantis_i2c_init(struct mantis_pci *mantis)220{221u32 intstat, intmask;222struct i2c_adapter *i2c_adapter = &mantis->adapter;223struct pci_dev *pdev = mantis->pdev;224225init_waitqueue_head(&mantis->i2c_wq);226mutex_init(&mantis->i2c_lock);227strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));228i2c_set_adapdata(i2c_adapter, mantis);229230i2c_adapter->owner = THIS_MODULE;231i2c_adapter->algo = &mantis_algo;232i2c_adapter->algo_data = NULL;233i2c_adapter->timeout = 500;234i2c_adapter->retries = 3;235i2c_adapter->dev.parent = &pdev->dev;236237mantis->i2c_rc = i2c_add_adapter(i2c_adapter);238if (mantis->i2c_rc < 0)239return mantis->i2c_rc;240241dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");242243intstat = mmread(MANTIS_INT_STAT);244intmask = mmread(MANTIS_INT_MASK);245mmwrite(intstat, MANTIS_INT_STAT);246dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");247intmask = mmread(MANTIS_INT_MASK);248mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);249250return 0;251}252EXPORT_SYMBOL_GPL(mantis_i2c_init);253254int mantis_i2c_exit(struct mantis_pci *mantis)255{256u32 intmask;257258dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");259intmask = mmread(MANTIS_INT_MASK);260mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);261262dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");263return i2c_del_adapter(&mantis->adapter);264}265EXPORT_SYMBOL_GPL(mantis_i2c_exit);266267268