linux/drivers/media/pci/mantis/mantis_i2c.c
<<
>>
Prefs
   1/*
   2        Mantis PCI bridge driver
   3
   4        Copyright (C) Manu Abraham (abraham.manu@gmail.com)
   5
   6        This program is free software; you can redistribute it and/or modify
   7        it under the terms of the GNU General Public License as published by
   8        the Free Software Foundation; either version 2 of the License, or
   9        (at your option) any later version.
  10
  11        This program is distributed in the hope that it will be useful,
  12        but WITHOUT ANY WARRANTY; without even the implied warranty of
  13        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14        GNU General Public License for more details.
  15
  16        You should have received a copy of the GNU General Public License
  17        along with this program; if not, write to the Free Software
  18        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19*/
  20
  21#include <asm/io.h>
  22#include <linux/ioport.h>
  23#include <linux/pci.h>
  24#include <linux/i2c.h>
  25
  26#include "dmxdev.h"
  27#include "dvbdev.h"
  28#include "dvb_demux.h"
  29#include "dvb_frontend.h"
  30#include "dvb_net.h"
  31
  32#include "mantis_common.h"
  33#include "mantis_reg.h"
  34#include "mantis_i2c.h"
  35
  36#define TRIALS                  10000
  37
  38static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
  39{
  40        u32 rxd, i, stat, trials;
  41
  42        dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
  43                __func__, msg->addr);
  44
  45        for (i = 0; i < msg->len; i++) {
  46                rxd = (msg->addr << 25) | (1 << 24)
  47                                        | MANTIS_I2C_RATE_3
  48                                        | MANTIS_I2C_STOP
  49                                        | MANTIS_I2C_PGMODE;
  50
  51                if (i == (msg->len - 1))
  52                        rxd &= ~MANTIS_I2C_STOP;
  53
  54                mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
  55                mmwrite(rxd, MANTIS_I2CDATA_CTL);
  56
  57                /* wait for xfer completion */
  58                for (trials = 0; trials < TRIALS; trials++) {
  59                        stat = mmread(MANTIS_INT_STAT);
  60                        if (stat & MANTIS_INT_I2CDONE)
  61                                break;
  62                }
  63
  64                dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
  65
  66                /* wait for xfer completion */
  67                for (trials = 0; trials < TRIALS; trials++) {
  68                        stat = mmread(MANTIS_INT_STAT);
  69                        if (stat & MANTIS_INT_I2CRACK)
  70                                break;
  71                }
  72
  73                dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
  74
  75                rxd = mmread(MANTIS_I2CDATA_CTL);
  76                msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
  77                dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
  78        }
  79        dprintk(MANTIS_INFO, 0, "]\n");
  80
  81        return 0;
  82}
  83
  84static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
  85{
  86        int i;
  87        u32 txd = 0, stat, trials;
  88
  89        dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
  90                __func__, msg->addr);
  91
  92        for (i = 0; i < msg->len; i++) {
  93                dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
  94                txd = (msg->addr << 25) | (msg->buf[i] << 8)
  95                                        | MANTIS_I2C_RATE_3
  96                                        | MANTIS_I2C_STOP
  97                                        | MANTIS_I2C_PGMODE;
  98
  99                if (i == (msg->len - 1))
 100                        txd &= ~MANTIS_I2C_STOP;
 101
 102                mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
 103                mmwrite(txd, MANTIS_I2CDATA_CTL);
 104
 105                /* wait for xfer completion */
 106                for (trials = 0; trials < TRIALS; trials++) {
 107                        stat = mmread(MANTIS_INT_STAT);
 108                        if (stat & MANTIS_INT_I2CDONE)
 109                                break;
 110                }
 111
 112                dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
 113
 114                /* wait for xfer completion */
 115                for (trials = 0; trials < TRIALS; trials++) {
 116                        stat = mmread(MANTIS_INT_STAT);
 117                        if (stat & MANTIS_INT_I2CRACK)
 118                                break;
 119                }
 120
 121                dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
 122        }
 123        dprintk(MANTIS_INFO, 0, "]\n");
 124
 125        return 0;
 126}
 127
 128static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 129{
 130        int ret = 0, i = 0, trials;
 131        u32 stat, data, txd;
 132        struct mantis_pci *mantis;
 133        struct mantis_hwconfig *config;
 134
 135        mantis = i2c_get_adapdata(adapter);
 136        BUG_ON(!mantis);
 137        config = mantis->hwconfig;
 138        BUG_ON(!config);
 139
 140        dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
 141        mutex_lock(&mantis->i2c_lock);
 142
 143        while (i < num) {
 144                /* Byte MODE */
 145                if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
 146                    ((i + 1) < num)                     &&
 147                    (msgs[i].len < 2)                   &&
 148                    (msgs[i + 1].len < 2)               &&
 149                    (msgs[i + 1].flags & I2C_M_RD)) {
 150
 151                        dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
 152
 153                        /* Read operation */
 154                        txd = msgs[i].addr << 25 | (0x1 << 24)
 155                                                 | (msgs[i].buf[0] << 16)
 156                                                 | MANTIS_I2C_RATE_3;
 157
 158                        mmwrite(txd, MANTIS_I2CDATA_CTL);
 159                        /* wait for xfer completion */
 160                        for (trials = 0; trials < TRIALS; trials++) {
 161                                stat = mmread(MANTIS_INT_STAT);
 162                                if (stat & MANTIS_INT_I2CDONE)
 163                                        break;
 164                        }
 165
 166                        /* check for xfer completion */
 167                        if (stat & MANTIS_INT_I2CDONE) {
 168                                /* check xfer was acknowledged */
 169                                if (stat & MANTIS_INT_I2CRACK) {
 170                                        data = mmread(MANTIS_I2CDATA_CTL);
 171                                        msgs[i + 1].buf[0] = (data >> 8) & 0xff;
 172                                        dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
 173                                } else {
 174                                        /* I/O error */
 175                                        dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
 176                                        ret = -EIO;
 177                                        break;
 178                                }
 179                        } else {
 180                                /* I/O error */
 181                                dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
 182                                ret = -EIO;
 183                                break;
 184                        }
 185                        i += 2; /* Write/Read operation in one go */
 186                }
 187
 188                if (i < num) {
 189                        if (msgs[i].flags & I2C_M_RD)
 190                                ret = mantis_i2c_read(mantis, &msgs[i]);
 191                        else
 192                                ret = mantis_i2c_write(mantis, &msgs[i]);
 193
 194                        i++;
 195                        if (ret < 0)
 196                                goto bail_out;
 197                }
 198
 199        }
 200
 201        mutex_unlock(&mantis->i2c_lock);
 202
 203        return num;
 204
 205bail_out:
 206        mutex_unlock(&mantis->i2c_lock);
 207        return ret;
 208}
 209
 210static u32 mantis_i2c_func(struct i2c_adapter *adapter)
 211{
 212        return I2C_FUNC_SMBUS_EMUL;
 213}
 214
 215static struct i2c_algorithm mantis_algo = {
 216        .master_xfer            = mantis_i2c_xfer,
 217        .functionality          = mantis_i2c_func,
 218};
 219
 220int mantis_i2c_init(struct mantis_pci *mantis)
 221{
 222        u32 intstat, intmask;
 223        struct i2c_adapter *i2c_adapter = &mantis->adapter;
 224        struct pci_dev *pdev            = mantis->pdev;
 225
 226        init_waitqueue_head(&mantis->i2c_wq);
 227        mutex_init(&mantis->i2c_lock);
 228        strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
 229        i2c_set_adapdata(i2c_adapter, mantis);
 230
 231        i2c_adapter->owner      = THIS_MODULE;
 232        i2c_adapter->algo       = &mantis_algo;
 233        i2c_adapter->algo_data  = NULL;
 234        i2c_adapter->timeout    = 500;
 235        i2c_adapter->retries    = 3;
 236        i2c_adapter->dev.parent = &pdev->dev;
 237
 238        mantis->i2c_rc          = i2c_add_adapter(i2c_adapter);
 239        if (mantis->i2c_rc < 0)
 240                return mantis->i2c_rc;
 241
 242        dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
 243
 244        intstat = mmread(MANTIS_INT_STAT);
 245        intmask = mmread(MANTIS_INT_MASK);
 246        mmwrite(intstat, MANTIS_INT_STAT);
 247        dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
 248        intmask = mmread(MANTIS_INT_MASK);
 249        mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
 250
 251        return 0;
 252}
 253EXPORT_SYMBOL_GPL(mantis_i2c_init);
 254
 255int mantis_i2c_exit(struct mantis_pci *mantis)
 256{
 257        u32 intmask;
 258
 259        dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
 260        intmask = mmread(MANTIS_INT_MASK);
 261        mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
 262
 263        dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
 264        i2c_del_adapter(&mantis->adapter);
 265
 266        return 0;
 267}
 268EXPORT_SYMBOL_GPL(mantis_i2c_exit);
 269