|
36 | 36 | #define USB5744_CMD_CREG_ACCESS 0x99 |
37 | 37 | #define USB5744_CMD_CREG_ACCESS_LSB 0x37 |
38 | 38 | #define USB5744_CREG_MEM_ADDR 0x00 |
| 39 | +#define USB5744_CREG_MEM_RD_ADDR 0x04 |
39 | 40 | #define USB5744_CREG_WRITE 0x00 |
40 | | -#define USB5744_CREG_RUNTIMEFLAGS2 0x41 |
41 | | -#define USB5744_CREG_RUNTIMEFLAGS2_LSB 0x1D |
| 41 | +#define USB5744_CREG_READ 0x01 |
| 42 | +#define USB5744_CREG_RUNTIMEFLAGS2 0x411D |
42 | 43 | #define USB5744_CREG_BYPASS_UDC_SUSPEND BIT(3) |
43 | 44 |
|
44 | 45 | static void onboard_dev_attach_usb_driver(struct work_struct *work); |
@@ -309,32 +310,105 @@ static void onboard_dev_attach_usb_driver(struct work_struct *work) |
309 | 310 | pr_err("Failed to attach USB driver: %pe\n", ERR_PTR(err)); |
310 | 311 | } |
311 | 312 |
|
| 313 | +static int onboard_dev_5744_i2c_read_byte(struct i2c_client *client, u16 addr, u8 *data) |
| 314 | +{ |
| 315 | + struct i2c_msg msg[2]; |
| 316 | + u8 rd_buf[3]; |
| 317 | + int ret; |
| 318 | + |
| 319 | + u8 wr_buf[7] = {0, USB5744_CREG_MEM_ADDR, 4, |
| 320 | + USB5744_CREG_READ, 1, |
| 321 | + addr >> 8 & 0xff, |
| 322 | + addr & 0xff}; |
| 323 | + msg[0].addr = client->addr; |
| 324 | + msg[0].flags = 0; |
| 325 | + msg[0].len = sizeof(wr_buf); |
| 326 | + msg[0].buf = wr_buf; |
| 327 | + |
| 328 | + ret = i2c_transfer(client->adapter, msg, 1); |
| 329 | + if (ret < 0) |
| 330 | + return ret; |
| 331 | + |
| 332 | + wr_buf[0] = USB5744_CMD_CREG_ACCESS; |
| 333 | + wr_buf[1] = USB5744_CMD_CREG_ACCESS_LSB; |
| 334 | + wr_buf[2] = 0; |
| 335 | + msg[0].len = 3; |
| 336 | + |
| 337 | + ret = i2c_transfer(client->adapter, msg, 1); |
| 338 | + if (ret < 0) |
| 339 | + return ret; |
| 340 | + |
| 341 | + wr_buf[0] = 0; |
| 342 | + wr_buf[1] = USB5744_CREG_MEM_RD_ADDR; |
| 343 | + msg[0].len = 2; |
| 344 | + |
| 345 | + msg[1].addr = client->addr; |
| 346 | + msg[1].flags = I2C_M_RD; |
| 347 | + msg[1].len = 2; |
| 348 | + msg[1].buf = rd_buf; |
| 349 | + |
| 350 | + ret = i2c_transfer(client->adapter, msg, 2); |
| 351 | + if (ret < 0) |
| 352 | + return ret; |
| 353 | + *data = rd_buf[1]; |
| 354 | + |
| 355 | + return 0; |
| 356 | +} |
| 357 | + |
| 358 | +static int onboard_dev_5744_i2c_write_byte(struct i2c_client *client, u16 addr, u8 data) |
| 359 | +{ |
| 360 | + struct i2c_msg msg[2]; |
| 361 | + int ret; |
| 362 | + |
| 363 | + u8 wr_buf[8] = {0, USB5744_CREG_MEM_ADDR, 5, |
| 364 | + USB5744_CREG_WRITE, 1, |
| 365 | + addr >> 8 & 0xff, |
| 366 | + addr & 0xff, |
| 367 | + data}; |
| 368 | + msg[0].addr = client->addr; |
| 369 | + msg[0].flags = 0; |
| 370 | + msg[0].len = sizeof(wr_buf); |
| 371 | + msg[0].buf = wr_buf; |
| 372 | + |
| 373 | + ret = i2c_transfer(client->adapter, msg, 1); |
| 374 | + if (ret < 0) |
| 375 | + return ret; |
| 376 | + |
| 377 | + msg[0].len = 3; |
| 378 | + wr_buf[0] = USB5744_CMD_CREG_ACCESS; |
| 379 | + wr_buf[1] = USB5744_CMD_CREG_ACCESS_LSB; |
| 380 | + wr_buf[2] = 0; |
| 381 | + |
| 382 | + ret = i2c_transfer(client->adapter, msg, 1); |
| 383 | + if (ret < 0) |
| 384 | + return ret; |
| 385 | + |
| 386 | + return 0; |
| 387 | +} |
| 388 | + |
312 | 389 | static int onboard_dev_5744_i2c_init(struct i2c_client *client) |
313 | 390 | { |
314 | 391 | #if IS_ENABLED(CONFIG_USB_ONBOARD_DEV_USB5744) |
315 | 392 | struct device *dev = &client->dev; |
316 | 393 | int ret; |
| 394 | + u8 reg; |
317 | 395 |
|
318 | 396 | /* |
319 | 397 | * Set BYPASS_UDC_SUSPEND bit to ensure MCU is always enabled |
320 | 398 | * and ready to respond to SMBus runtime commands. |
321 | 399 | * The command writes 5 bytes to memory and single data byte in |
322 | 400 | * configuration register. |
323 | 401 | */ |
324 | | - char wr_buf[7] = {USB5744_CREG_MEM_ADDR, 5, |
325 | | - USB5744_CREG_WRITE, 1, |
326 | | - USB5744_CREG_RUNTIMEFLAGS2, |
327 | | - USB5744_CREG_RUNTIMEFLAGS2_LSB, |
328 | | - USB5744_CREG_BYPASS_UDC_SUSPEND}; |
329 | | - |
330 | | - ret = i2c_smbus_write_block_data(client, 0, sizeof(wr_buf), wr_buf); |
| 402 | + ret = onboard_dev_5744_i2c_read_byte(client, |
| 403 | + USB5744_CREG_RUNTIMEFLAGS2, ®); |
331 | 404 | if (ret) |
332 | | - return dev_err_probe(dev, ret, "BYPASS_UDC_SUSPEND bit configuration failed\n"); |
| 405 | + return dev_err_probe(dev, ret, "CREG_RUNTIMEFLAGS2 read failed\n"); |
333 | 406 |
|
334 | | - ret = i2c_smbus_write_word_data(client, USB5744_CMD_CREG_ACCESS, |
335 | | - USB5744_CMD_CREG_ACCESS_LSB); |
| 407 | + reg |= USB5744_CREG_BYPASS_UDC_SUSPEND; |
| 408 | + ret = onboard_dev_5744_i2c_write_byte(client, |
| 409 | + USB5744_CREG_RUNTIMEFLAGS2, reg); |
336 | 410 | if (ret) |
337 | | - return dev_err_probe(dev, ret, "Configuration Register Access Command failed\n"); |
| 411 | + return dev_err_probe(dev, ret, "BYPASS_UDC_SUSPEND bit configuration failed\n"); |
338 | 412 |
|
339 | 413 | /* Send SMBus command to boot hub. */ |
340 | 414 | ret = i2c_smbus_write_word_data(client, USB5744_CMD_ATTACH, |
|
0 commit comments