diff options
-rw-r--r-- | drivers/i3c/master.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index b9d2b88928e1..54026be03998 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c | |||
@@ -91,6 +91,12 @@ void i3c_bus_normaluse_unlock(struct i3c_bus *bus) | |||
91 | up_read(&bus->lock); | 91 | up_read(&bus->lock); |
92 | } | 92 | } |
93 | 93 | ||
94 | static struct i3c_master_controller * | ||
95 | i3c_bus_to_i3c_master(struct i3c_bus *i3cbus) | ||
96 | { | ||
97 | return container_of(i3cbus, struct i3c_master_controller, bus); | ||
98 | } | ||
99 | |||
94 | static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev) | 100 | static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev) |
95 | { | 101 | { |
96 | return container_of(dev, struct i3c_master_controller, dev); | 102 | return container_of(dev, struct i3c_master_controller, dev); |
@@ -565,20 +571,38 @@ static const struct device_type i3c_masterdev_type = { | |||
565 | .groups = i3c_masterdev_groups, | 571 | .groups = i3c_masterdev_groups, |
566 | }; | 572 | }; |
567 | 573 | ||
568 | int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode) | 574 | int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode, |
575 | unsigned long max_i2c_scl_rate) | ||
569 | { | 576 | { |
570 | i3cbus->mode = mode; | 577 | struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus); |
571 | 578 | ||
572 | if (!i3cbus->scl_rate.i3c) | 579 | i3cbus->mode = mode; |
573 | i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE; | ||
574 | 580 | ||
575 | if (!i3cbus->scl_rate.i2c) { | 581 | switch (i3cbus->mode) { |
576 | if (i3cbus->mode == I3C_BUS_MODE_MIXED_SLOW) | 582 | case I3C_BUS_MODE_PURE: |
577 | i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE; | 583 | if (!i3cbus->scl_rate.i3c) |
578 | else | 584 | i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE; |
579 | i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_PLUS_SCL_RATE; | 585 | break; |
586 | case I3C_BUS_MODE_MIXED_FAST: | ||
587 | if (!i3cbus->scl_rate.i3c) | ||
588 | i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE; | ||
589 | if (!i3cbus->scl_rate.i2c) | ||
590 | i3cbus->scl_rate.i2c = max_i2c_scl_rate; | ||
591 | break; | ||
592 | case I3C_BUS_MODE_MIXED_SLOW: | ||
593 | if (!i3cbus->scl_rate.i2c) | ||
594 | i3cbus->scl_rate.i2c = max_i2c_scl_rate; | ||
595 | if (!i3cbus->scl_rate.i3c || | ||
596 | i3cbus->scl_rate.i3c > i3cbus->scl_rate.i2c) | ||
597 | i3cbus->scl_rate.i3c = i3cbus->scl_rate.i2c; | ||
598 | break; | ||
599 | default: | ||
600 | return -EINVAL; | ||
580 | } | 601 | } |
581 | 602 | ||
603 | dev_dbg(&master->dev, "i2c-scl = %ld Hz i3c-scl = %ld Hz\n", | ||
604 | i3cbus->scl_rate.i2c, i3cbus->scl_rate.i3c); | ||
605 | |||
582 | /* | 606 | /* |
583 | * I3C/I2C frequency may have been overridden, check that user-provided | 607 | * I3C/I2C frequency may have been overridden, check that user-provided |
584 | * values are not exceeding max possible frequency. | 608 | * values are not exceeding max possible frequency. |
@@ -1976,9 +2000,6 @@ of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master, | |||
1976 | /* LVR is encoded in reg[2]. */ | 2000 | /* LVR is encoded in reg[2]. */ |
1977 | boardinfo->lvr = reg[2]; | 2001 | boardinfo->lvr = reg[2]; |
1978 | 2002 | ||
1979 | if (boardinfo->lvr & I3C_LVR_I2C_FM_MODE) | ||
1980 | master->bus.scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE; | ||
1981 | |||
1982 | list_add_tail(&boardinfo->node, &master->boardinfo.i2c); | 2003 | list_add_tail(&boardinfo->node, &master->boardinfo.i2c); |
1983 | of_node_get(node); | 2004 | of_node_get(node); |
1984 | 2005 | ||
@@ -2424,6 +2445,7 @@ int i3c_master_register(struct i3c_master_controller *master, | |||
2424 | const struct i3c_master_controller_ops *ops, | 2445 | const struct i3c_master_controller_ops *ops, |
2425 | bool secondary) | 2446 | bool secondary) |
2426 | { | 2447 | { |
2448 | unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE; | ||
2427 | struct i3c_bus *i3cbus = i3c_master_get_bus(master); | 2449 | struct i3c_bus *i3cbus = i3c_master_get_bus(master); |
2428 | enum i3c_bus_mode mode = I3C_BUS_MODE_PURE; | 2450 | enum i3c_bus_mode mode = I3C_BUS_MODE_PURE; |
2429 | struct i2c_dev_boardinfo *i2cbi; | 2451 | struct i2c_dev_boardinfo *i2cbi; |
@@ -2473,9 +2495,12 @@ int i3c_master_register(struct i3c_master_controller *master, | |||
2473 | ret = -EINVAL; | 2495 | ret = -EINVAL; |
2474 | goto err_put_dev; | 2496 | goto err_put_dev; |
2475 | } | 2497 | } |
2498 | |||
2499 | if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE) | ||
2500 | i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE; | ||
2476 | } | 2501 | } |
2477 | 2502 | ||
2478 | ret = i3c_bus_set_mode(i3cbus, mode); | 2503 | ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate); |
2479 | if (ret) | 2504 | if (ret) |
2480 | goto err_put_dev; | 2505 | goto err_put_dev; |
2481 | 2506 | ||