root/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bit.c

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

DEFINITIONS

This source file includes following definitions.
  1. nvkm_i2c_drive_scl
  2. nvkm_i2c_drive_sda
  3. nvkm_i2c_sense_scl
  4. nvkm_i2c_sense_sda
  5. nvkm_i2c_delay
  6. nvkm_i2c_raise_scl
  7. i2c_start
  8. i2c_stop
  9. i2c_bitw
  10. i2c_bitr
  11. nvkm_i2c_get_byte
  12. nvkm_i2c_put_byte
  13. i2c_addr
  14. nvkm_i2c_bit_xfer
  15. nvkm_i2c_bit_xfer

   1 /*
   2  * Copyright 2012 Red Hat Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial busions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: Ben Skeggs
  23  */
  24 #include "bus.h"
  25 
  26 #ifdef CONFIG_NOUVEAU_I2C_INTERNAL
  27 #define T_TIMEOUT  2200000
  28 #define T_RISEFALL 1000
  29 #define T_HOLD     5000
  30 
  31 static inline void
  32 nvkm_i2c_drive_scl(struct nvkm_i2c_bus *bus, int state)
  33 {
  34         bus->func->drive_scl(bus, state);
  35 }
  36 
  37 static inline void
  38 nvkm_i2c_drive_sda(struct nvkm_i2c_bus *bus, int state)
  39 {
  40         bus->func->drive_sda(bus, state);
  41 }
  42 
  43 static inline int
  44 nvkm_i2c_sense_scl(struct nvkm_i2c_bus *bus)
  45 {
  46         return bus->func->sense_scl(bus);
  47 }
  48 
  49 static inline int
  50 nvkm_i2c_sense_sda(struct nvkm_i2c_bus *bus)
  51 {
  52         return bus->func->sense_sda(bus);
  53 }
  54 
  55 static void
  56 nvkm_i2c_delay(struct nvkm_i2c_bus *bus, u32 nsec)
  57 {
  58         udelay((nsec + 500) / 1000);
  59 }
  60 
  61 static bool
  62 nvkm_i2c_raise_scl(struct nvkm_i2c_bus *bus)
  63 {
  64         u32 timeout = T_TIMEOUT / T_RISEFALL;
  65 
  66         nvkm_i2c_drive_scl(bus, 1);
  67         do {
  68                 nvkm_i2c_delay(bus, T_RISEFALL);
  69         } while (!nvkm_i2c_sense_scl(bus) && --timeout);
  70 
  71         return timeout != 0;
  72 }
  73 
  74 static int
  75 i2c_start(struct nvkm_i2c_bus *bus)
  76 {
  77         int ret = 0;
  78 
  79         if (!nvkm_i2c_sense_scl(bus) ||
  80             !nvkm_i2c_sense_sda(bus)) {
  81                 nvkm_i2c_drive_scl(bus, 0);
  82                 nvkm_i2c_drive_sda(bus, 1);
  83                 if (!nvkm_i2c_raise_scl(bus))
  84                         ret = -EBUSY;
  85         }
  86 
  87         nvkm_i2c_drive_sda(bus, 0);
  88         nvkm_i2c_delay(bus, T_HOLD);
  89         nvkm_i2c_drive_scl(bus, 0);
  90         nvkm_i2c_delay(bus, T_HOLD);
  91         return ret;
  92 }
  93 
  94 static void
  95 i2c_stop(struct nvkm_i2c_bus *bus)
  96 {
  97         nvkm_i2c_drive_scl(bus, 0);
  98         nvkm_i2c_drive_sda(bus, 0);
  99         nvkm_i2c_delay(bus, T_RISEFALL);
 100 
 101         nvkm_i2c_drive_scl(bus, 1);
 102         nvkm_i2c_delay(bus, T_HOLD);
 103         nvkm_i2c_drive_sda(bus, 1);
 104         nvkm_i2c_delay(bus, T_HOLD);
 105 }
 106 
 107 static int
 108 i2c_bitw(struct nvkm_i2c_bus *bus, int sda)
 109 {
 110         nvkm_i2c_drive_sda(bus, sda);
 111         nvkm_i2c_delay(bus, T_RISEFALL);
 112 
 113         if (!nvkm_i2c_raise_scl(bus))
 114                 return -ETIMEDOUT;
 115         nvkm_i2c_delay(bus, T_HOLD);
 116 
 117         nvkm_i2c_drive_scl(bus, 0);
 118         nvkm_i2c_delay(bus, T_HOLD);
 119         return 0;
 120 }
 121 
 122 static int
 123 i2c_bitr(struct nvkm_i2c_bus *bus)
 124 {
 125         int sda;
 126 
 127         nvkm_i2c_drive_sda(bus, 1);
 128         nvkm_i2c_delay(bus, T_RISEFALL);
 129 
 130         if (!nvkm_i2c_raise_scl(bus))
 131                 return -ETIMEDOUT;
 132         nvkm_i2c_delay(bus, T_HOLD);
 133 
 134         sda = nvkm_i2c_sense_sda(bus);
 135 
 136         nvkm_i2c_drive_scl(bus, 0);
 137         nvkm_i2c_delay(bus, T_HOLD);
 138         return sda;
 139 }
 140 
 141 static int
 142 nvkm_i2c_get_byte(struct nvkm_i2c_bus *bus, u8 *byte, bool last)
 143 {
 144         int i, bit;
 145 
 146         *byte = 0;
 147         for (i = 7; i >= 0; i--) {
 148                 bit = i2c_bitr(bus);
 149                 if (bit < 0)
 150                         return bit;
 151                 *byte |= bit << i;
 152         }
 153 
 154         return i2c_bitw(bus, last ? 1 : 0);
 155 }
 156 
 157 static int
 158 nvkm_i2c_put_byte(struct nvkm_i2c_bus *bus, u8 byte)
 159 {
 160         int i, ret;
 161         for (i = 7; i >= 0; i--) {
 162                 ret = i2c_bitw(bus, !!(byte & (1 << i)));
 163                 if (ret < 0)
 164                         return ret;
 165         }
 166 
 167         ret = i2c_bitr(bus);
 168         if (ret == 1) /* nack */
 169                 ret = -EIO;
 170         return ret;
 171 }
 172 
 173 static int
 174 i2c_addr(struct nvkm_i2c_bus *bus, struct i2c_msg *msg)
 175 {
 176         u32 addr = msg->addr << 1;
 177         if (msg->flags & I2C_M_RD)
 178                 addr |= 1;
 179         return nvkm_i2c_put_byte(bus, addr);
 180 }
 181 
 182 int
 183 nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *bus, struct i2c_msg *msgs, int num)
 184 {
 185         struct i2c_msg *msg = msgs;
 186         int ret = 0, mcnt = num;
 187 
 188         while (!ret && mcnt--) {
 189                 u8 remaining = msg->len;
 190                 u8 *ptr = msg->buf;
 191 
 192                 ret = i2c_start(bus);
 193                 if (ret == 0)
 194                         ret = i2c_addr(bus, msg);
 195 
 196                 if (msg->flags & I2C_M_RD) {
 197                         while (!ret && remaining--)
 198                                 ret = nvkm_i2c_get_byte(bus, ptr++, !remaining);
 199                 } else {
 200                         while (!ret && remaining--)
 201                                 ret = nvkm_i2c_put_byte(bus, *ptr++);
 202                 }
 203 
 204                 msg++;
 205         }
 206 
 207         i2c_stop(bus);
 208         return (ret < 0) ? ret : num;
 209 }
 210 #else
 211 int
 212 nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *bus, struct i2c_msg *msgs, int num)
 213 {
 214         return -ENODEV;
 215 }
 216 #endif

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