root/drivers/media/pci/ngene/ngene-i2c.c

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

DEFINITIONS

This source file includes following definitions.
  1. ngene_command_i2c_read
  2. ngene_command_i2c_write
  3. ngene_i2c_set_bus
  4. ngene_i2c_master_xfer
  5. ngene_i2c_functionality
  6. ngene_i2c_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ngene-i2c.c: nGene PCIe bridge driver i2c functions
   4  *
   5  * Copyright (C) 2005-2007 Micronas
   6  *
   7  * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
   8  *                         Modifications for new nGene firmware,
   9  *                         support for EEPROM-copying,
  10  *                         support for new dual DVB-S2 card prototype
  11  */
  12 
  13 /* FIXME - some of these can probably be removed */
  14 #include <linux/module.h>
  15 #include <linux/init.h>
  16 #include <linux/delay.h>
  17 #include <linux/slab.h>
  18 #include <linux/poll.h>
  19 #include <linux/io.h>
  20 #include <asm/div64.h>
  21 #include <linux/pci.h>
  22 #include <linux/pci_ids.h>
  23 #include <linux/timer.h>
  24 #include <linux/byteorder/generic.h>
  25 #include <linux/firmware.h>
  26 #include <linux/vmalloc.h>
  27 
  28 #include "ngene.h"
  29 
  30 /* Firmware command for i2c operations */
  31 static int ngene_command_i2c_read(struct ngene *dev, u8 adr,
  32                            u8 *out, u8 outlen, u8 *in, u8 inlen, int flag)
  33 {
  34         struct ngene_command com;
  35 
  36         com.cmd.hdr.Opcode = CMD_I2C_READ;
  37         com.cmd.hdr.Length = outlen + 3;
  38         com.cmd.I2CRead.Device = adr << 1;
  39         memcpy(com.cmd.I2CRead.Data, out, outlen);
  40         com.cmd.I2CRead.Data[outlen] = inlen;
  41         com.cmd.I2CRead.Data[outlen + 1] = 0;
  42         com.in_len = outlen + 3;
  43         com.out_len = inlen + 1;
  44 
  45         if (ngene_command(dev, &com) < 0)
  46                 return -EIO;
  47 
  48         if ((com.cmd.raw8[0] >> 1) != adr)
  49                 return -EIO;
  50 
  51         if (flag)
  52                 memcpy(in, com.cmd.raw8, inlen + 1);
  53         else
  54                 memcpy(in, com.cmd.raw8 + 1, inlen);
  55         return 0;
  56 }
  57 
  58 static int ngene_command_i2c_write(struct ngene *dev, u8 adr,
  59                                    u8 *out, u8 outlen)
  60 {
  61         struct ngene_command com;
  62 
  63 
  64         com.cmd.hdr.Opcode = CMD_I2C_WRITE;
  65         com.cmd.hdr.Length = outlen + 1;
  66         com.cmd.I2CRead.Device = adr << 1;
  67         memcpy(com.cmd.I2CRead.Data, out, outlen);
  68         com.in_len = outlen + 1;
  69         com.out_len = 1;
  70 
  71         if (ngene_command(dev, &com) < 0)
  72                 return -EIO;
  73 
  74         if (com.cmd.raw8[0] == 1)
  75                 return -EIO;
  76 
  77         return 0;
  78 }
  79 
  80 static void ngene_i2c_set_bus(struct ngene *dev, int bus)
  81 {
  82         if (!(dev->card_info->i2c_access & 2))
  83                 return;
  84         if (dev->i2c_current_bus == bus)
  85                 return;
  86 
  87         switch (bus) {
  88         case 0:
  89                 ngene_command_gpio_set(dev, 3, 0);
  90                 ngene_command_gpio_set(dev, 2, 1);
  91                 break;
  92 
  93         case 1:
  94                 ngene_command_gpio_set(dev, 2, 0);
  95                 ngene_command_gpio_set(dev, 3, 1);
  96                 break;
  97         }
  98         dev->i2c_current_bus = bus;
  99 }
 100 
 101 static int ngene_i2c_master_xfer(struct i2c_adapter *adapter,
 102                                  struct i2c_msg msg[], int num)
 103 {
 104         struct ngene_channel *chan =
 105                 (struct ngene_channel *)i2c_get_adapdata(adapter);
 106         struct ngene *dev = chan->dev;
 107 
 108         mutex_lock(&dev->i2c_switch_mutex);
 109         ngene_i2c_set_bus(dev, chan->number);
 110 
 111         if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD))
 112                 if (!ngene_command_i2c_read(dev, msg[0].addr,
 113                                             msg[0].buf, msg[0].len,
 114                                             msg[1].buf, msg[1].len, 0))
 115                         goto done;
 116 
 117         if (num == 1 && !(msg[0].flags & I2C_M_RD))
 118                 if (!ngene_command_i2c_write(dev, msg[0].addr,
 119                                              msg[0].buf, msg[0].len))
 120                         goto done;
 121         if (num == 1 && (msg[0].flags & I2C_M_RD))
 122                 if (!ngene_command_i2c_read(dev, msg[0].addr, NULL, 0,
 123                                             msg[0].buf, msg[0].len, 0))
 124                         goto done;
 125 
 126         mutex_unlock(&dev->i2c_switch_mutex);
 127         return -EIO;
 128 
 129 done:
 130         mutex_unlock(&dev->i2c_switch_mutex);
 131         return num;
 132 }
 133 
 134 
 135 static u32 ngene_i2c_functionality(struct i2c_adapter *adap)
 136 {
 137         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 138 }
 139 
 140 static const struct i2c_algorithm ngene_i2c_algo = {
 141         .master_xfer = ngene_i2c_master_xfer,
 142         .functionality = ngene_i2c_functionality,
 143 };
 144 
 145 int ngene_i2c_init(struct ngene *dev, int dev_nr)
 146 {
 147         struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter);
 148 
 149         i2c_set_adapdata(adap, &(dev->channel[dev_nr]));
 150 
 151         strscpy(adap->name, "nGene", sizeof(adap->name));
 152 
 153         adap->algo = &ngene_i2c_algo;
 154         adap->algo_data = (void *)&(dev->channel[dev_nr]);
 155         adap->dev.parent = &dev->pci_dev->dev;
 156 
 157         return i2c_add_adapter(adap);
 158 }
 159 

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