root/drivers/media/pci/mantis/mantis_i2c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mantis_i2c_read
  2. mantis_i2c_write
  3. mantis_i2c_xfer
  4. mantis_i2c_func
  5. mantis_i2c_init
  6. mantis_i2c_exit

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

/* [<][>][^][v][top][bottom][index][help] */