|
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