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