Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/nouveau/i2c: handle bit-banging ourselves

i2c-algo-bit doesn't actually work very well on one card I have access to
(NVS 300), random single-bit errors occur most of the time - what we're
doing now is closer to what xf86i2c.c does.

The original plan was to figure out why i2c-algo-bit fails on the NVS 300,
and fix it. However, while investigating I discovered i2c-algo-bit calls
cond_resched(), which makes it a bad idea for us to be using as we execute
VBIOS scripts from a tasklet, and there may very well be i2c transfers as
a result.

So, since I already wrote this code in userspace to track down the NVS 300
bug, and it's not really much code - lets use it.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>

+178 -22
+178 -21
drivers/gpu/drm/nouveau/nouveau_i2c.c
··· 29 29 #include "nouveau_i2c.h" 30 30 #include "nouveau_hw.h" 31 31 32 + #define T_TIMEOUT 2200000 33 + #define T_RISEFALL 1000 34 + #define T_HOLD 5000 35 + 32 36 static void 33 37 i2c_drive_scl(void *data, int state) 34 38 { ··· 112 108 } 113 109 return 0; 114 110 } 111 + 112 + static void 113 + i2c_delay(struct nouveau_i2c_chan *port, u32 nsec) 114 + { 115 + udelay((nsec + 500) / 1000); 116 + } 117 + 118 + static bool 119 + i2c_raise_scl(struct nouveau_i2c_chan *port) 120 + { 121 + u32 timeout = T_TIMEOUT / T_RISEFALL; 122 + 123 + i2c_drive_scl(port, 1); 124 + do { 125 + i2c_delay(port, T_RISEFALL); 126 + } while (!i2c_sense_scl(port) && --timeout); 127 + 128 + return timeout != 0; 129 + } 130 + 131 + static int 132 + i2c_start(struct nouveau_i2c_chan *port) 133 + { 134 + int ret = 0; 135 + 136 + port->state = i2c_sense_scl(port); 137 + port->state |= i2c_sense_sda(port) << 1; 138 + if (port->state != 3) { 139 + i2c_drive_scl(port, 0); 140 + i2c_drive_sda(port, 1); 141 + if (!i2c_raise_scl(port)) 142 + ret = -EBUSY; 143 + } 144 + 145 + i2c_drive_sda(port, 0); 146 + i2c_delay(port, T_HOLD); 147 + i2c_drive_scl(port, 0); 148 + i2c_delay(port, T_HOLD); 149 + return ret; 150 + } 151 + 152 + static void 153 + i2c_stop(struct nouveau_i2c_chan *port) 154 + { 155 + i2c_drive_scl(port, 0); 156 + i2c_drive_sda(port, 0); 157 + i2c_delay(port, T_RISEFALL); 158 + 159 + i2c_drive_scl(port, 1); 160 + i2c_delay(port, T_HOLD); 161 + i2c_drive_sda(port, 1); 162 + i2c_delay(port, T_HOLD); 163 + } 164 + 165 + static int 166 + i2c_bitw(struct nouveau_i2c_chan *port, int sda) 167 + { 168 + i2c_drive_sda(port, sda); 169 + i2c_delay(port, T_RISEFALL); 170 + 171 + if (!i2c_raise_scl(port)) 172 + return -ETIMEDOUT; 173 + i2c_delay(port, T_HOLD); 174 + 175 + i2c_drive_scl(port, 0); 176 + i2c_delay(port, T_HOLD); 177 + return 0; 178 + } 179 + 180 + static int 181 + i2c_bitr(struct nouveau_i2c_chan *port) 182 + { 183 + int sda; 184 + 185 + i2c_drive_sda(port, 1); 186 + i2c_delay(port, T_RISEFALL); 187 + 188 + if (!i2c_raise_scl(port)) 189 + return -ETIMEDOUT; 190 + i2c_delay(port, T_HOLD); 191 + 192 + sda = i2c_sense_sda(port); 193 + 194 + i2c_drive_scl(port, 0); 195 + i2c_delay(port, T_HOLD); 196 + return sda; 197 + } 198 + 199 + static int 200 + i2c_get_byte(struct nouveau_i2c_chan *port, u8 *byte, bool last) 201 + { 202 + int i, bit; 203 + 204 + *byte = 0; 205 + for (i = 7; i >= 0; i--) { 206 + bit = i2c_bitr(port); 207 + if (bit < 0) 208 + return bit; 209 + *byte |= bit << i; 210 + } 211 + 212 + return i2c_bitw(port, last ? 1 : 0); 213 + } 214 + 215 + static int 216 + i2c_put_byte(struct nouveau_i2c_chan *port, u8 byte) 217 + { 218 + int i, ret; 219 + for (i = 7; i >= 0; i--) { 220 + ret = i2c_bitw(port, !!(byte & (1 << i))); 221 + if (ret < 0) 222 + return ret; 223 + } 224 + 225 + ret = i2c_bitr(port); 226 + if (ret == 1) /* nack */ 227 + ret = -EIO; 228 + return ret; 229 + } 230 + 231 + static int 232 + i2c_addr(struct nouveau_i2c_chan *port, struct i2c_msg *msg) 233 + { 234 + u32 addr = msg->addr << 1; 235 + if (msg->flags & I2C_M_RD) 236 + addr |= 1; 237 + return i2c_put_byte(port, addr); 238 + } 239 + 240 + static int 241 + i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 242 + { 243 + struct nouveau_i2c_chan *port = (struct nouveau_i2c_chan *)adap; 244 + struct i2c_msg *msg = msgs; 245 + int ret = 0, mcnt = num; 246 + 247 + while (!ret && mcnt--) { 248 + u8 remaining = msg->len; 249 + u8 *ptr = msg->buf; 250 + 251 + ret = i2c_start(port); 252 + if (ret == 0) 253 + ret = i2c_addr(port, msg); 254 + 255 + if (msg->flags & I2C_M_RD) { 256 + while (!ret && remaining--) 257 + ret = i2c_get_byte(port, ptr++, !remaining); 258 + } else { 259 + while (!ret && remaining--) 260 + ret = i2c_put_byte(port, *ptr++); 261 + } 262 + 263 + msg++; 264 + } 265 + 266 + i2c_stop(port); 267 + return (ret < 0) ? ret : num; 268 + } 269 + 270 + static u32 271 + i2c_bit_func(struct i2c_adapter *adap) 272 + { 273 + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 274 + } 275 + 276 + const struct i2c_algorithm i2c_bit_algo = { 277 + .master_xfer = i2c_bit_xfer, 278 + .functionality = i2c_bit_func 279 + }; 115 280 116 281 static const uint32_t nv50_i2c_port[] = { 117 282 0x00e138, 0x00e150, 0x00e168, 0x00e180, ··· 384 211 case 0: /* NV04:NV50 */ 385 212 port->drive = entry[0]; 386 213 port->sense = entry[1]; 214 + port->adapter.algo = &i2c_bit_algo; 387 215 break; 388 216 case 4: /* NV4E */ 389 217 port->drive = 0x600800 + entry[1]; 390 218 port->sense = port->drive; 219 + port->adapter.algo = &i2c_bit_algo; 391 220 break; 392 221 case 5: /* NV50- */ 393 222 port->drive = entry[0] & 0x0f; ··· 402 227 port->drive = 0x00d014 + (port->drive * 0x20); 403 228 port->sense = port->drive; 404 229 } 230 + port->adapter.algo = &i2c_bit_algo; 405 231 break; 406 232 case 6: /* NV50- DP AUX */ 407 233 port->drive = entry[0]; ··· 413 237 break; 414 238 } 415 239 416 - if (!port->adapter.algo && !port->drive) { 240 + if (!port->adapter.algo) { 417 241 NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", 418 242 i, port->type, port->drive, port->sense); 419 243 kfree(port); ··· 429 253 port->dcb = ROM32(entry[0]); 430 254 i2c_set_adapdata(&port->adapter, i2c); 431 255 432 - if (port->adapter.algo != &nouveau_dp_i2c_algo) { 433 - port->adapter.algo_data = &port->bit; 434 - port->bit.udelay = 40; 435 - port->bit.timeout = usecs_to_jiffies(5000); 436 - port->bit.data = port; 437 - port->bit.setsda = i2c_drive_sda; 438 - port->bit.setscl = i2c_drive_scl; 439 - port->bit.getsda = i2c_sense_sda; 440 - port->bit.getscl = i2c_sense_scl; 441 - 442 - i2c_drive_scl(port, 0); 443 - i2c_drive_sda(port, 1); 444 - i2c_drive_scl(port, 1); 445 - 446 - ret = i2c_bit_add_bus(&port->adapter); 447 - } else { 448 - port->adapter.algo = &nouveau_dp_i2c_algo; 449 - ret = i2c_add_adapter(&port->adapter); 450 - } 451 - 256 + ret = i2c_add_adapter(&port->adapter); 452 257 if (ret) { 453 258 NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); 454 259 kfree(port);
-1
drivers/gpu/drm/nouveau/nouveau_i2c.h
··· 34 34 struct nouveau_i2c_chan { 35 35 struct i2c_adapter adapter; 36 36 struct drm_device *dev; 37 - struct i2c_algo_bit_data bit; 38 37 struct list_head head; 39 38 u8 index; 40 39 u8 type;