@@ -1373,7 +1373,9 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
1373
1373
enum i3c_addr_slot_status status ;
1374
1374
int ret ;
1375
1375
1376
- if (dev -> info .dyn_addr != old_dyn_addr ) {
1376
+ if (dev -> info .dyn_addr != old_dyn_addr &&
1377
+ (!dev -> boardinfo ||
1378
+ dev -> info .dyn_addr != dev -> boardinfo -> init_dyn_addr )) {
1377
1379
status = i3c_bus_get_addr_slot_status (& master -> bus ,
1378
1380
dev -> info .dyn_addr );
1379
1381
if (status != I3C_ADDR_SLOT_FREE )
@@ -1432,33 +1434,49 @@ static void i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
1432
1434
master -> ops -> detach_i2c_dev (dev );
1433
1435
}
1434
1436
1435
- static void i3c_master_pre_assign_dyn_addr (struct i3c_dev_desc * dev )
1437
+ static int i3c_master_early_i3c_dev_add (struct i3c_master_controller * master ,
1438
+ struct i3c_dev_boardinfo * boardinfo )
1436
1439
{
1437
- struct i3c_master_controller * master = i3c_dev_get_master (dev );
1440
+ struct i3c_device_info info = {
1441
+ .static_addr = boardinfo -> static_addr ,
1442
+ };
1443
+ struct i3c_dev_desc * i3cdev ;
1438
1444
int ret ;
1439
1445
1440
- if (!dev -> boardinfo || !dev -> boardinfo -> init_dyn_addr ||
1441
- !dev -> boardinfo -> static_addr )
1442
- return ;
1446
+ i3cdev = i3c_master_alloc_i3c_dev (master , & info );
1447
+ if (IS_ERR (i3cdev ))
1448
+ return - ENOMEM ;
1449
+
1450
+ i3cdev -> boardinfo = boardinfo ;
1451
+
1452
+ ret = i3c_master_attach_i3c_dev (master , i3cdev );
1453
+ if (ret )
1454
+ goto err_free_dev ;
1443
1455
1444
- ret = i3c_master_setdasa_locked (master , dev -> info .static_addr ,
1445
- dev -> boardinfo -> init_dyn_addr );
1456
+ ret = i3c_master_setdasa_locked (master , i3cdev -> info .static_addr ,
1457
+ i3cdev -> boardinfo -> init_dyn_addr );
1446
1458
if (ret )
1447
- return ;
1459
+ goto err_detach_dev ;
1448
1460
1449
- dev -> info .dyn_addr = dev -> boardinfo -> init_dyn_addr ;
1450
- ret = i3c_master_reattach_i3c_dev (dev , 0 );
1461
+ i3cdev -> info .dyn_addr = i3cdev -> boardinfo -> init_dyn_addr ;
1462
+ ret = i3c_master_reattach_i3c_dev (i3cdev , 0 );
1451
1463
if (ret )
1452
1464
goto err_rstdaa ;
1453
1465
1454
- ret = i3c_master_retrieve_dev_info (dev );
1466
+ ret = i3c_master_retrieve_dev_info (i3cdev );
1455
1467
if (ret )
1456
1468
goto err_rstdaa ;
1457
1469
1458
- return ;
1470
+ return 0 ;
1459
1471
1460
1472
err_rstdaa :
1461
- i3c_master_rstdaa_locked (master , dev -> boardinfo -> init_dyn_addr );
1473
+ i3c_master_rstdaa_locked (master , i3cdev -> boardinfo -> init_dyn_addr );
1474
+ err_detach_dev :
1475
+ i3c_master_detach_i3c_dev (i3cdev );
1476
+ err_free_dev :
1477
+ i3c_master_free_i3c_dev (i3cdev );
1478
+
1479
+ return ret ;
1462
1480
}
1463
1481
1464
1482
static void
@@ -1625,8 +1643,8 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
1625
1643
* This function is following all initialisation steps described in the I3C
1626
1644
* specification:
1627
1645
*
1628
- * 1. Attach I2C and statically defined I3C devs to the master so that the
1629
- * master can fill its internal device table appropriately
1646
+ * 1. Attach I2C devs to the master so that the master can fill its internal
1647
+ * device table appropriately
1630
1648
*
1631
1649
* 2. Call &i3c_master_controller_ops->bus_init() method to initialize
1632
1650
* the master controller. That's usually where the bus mode is selected
@@ -1638,8 +1656,10 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
1638
1656
*
1639
1657
* 4. Disable all slave events.
1640
1658
*
1641
- * 5. Pre-assign dynamic addresses requested by the FW with SETDASA for I3C
1642
- * devices that have a static address
1659
+ * 5. Reserve address slots for I3C devices with init_dyn_addr. And if devices
1660
+ * also have static_addr, try to pre-assign dynamic addresses requested by
1661
+ * the FW with SETDASA and attach corresponding statically defined I3C
1662
+ * devices to the master.
1643
1663
*
1644
1664
* 6. Do a DAA (Dynamic Address Assignment) to assign dynamic addresses to all
1645
1665
* remaining I3C devices
@@ -1653,7 +1673,6 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
1653
1673
enum i3c_addr_slot_status status ;
1654
1674
struct i2c_dev_boardinfo * i2cboardinfo ;
1655
1675
struct i3c_dev_boardinfo * i3cboardinfo ;
1656
- struct i3c_dev_desc * i3cdev ;
1657
1676
struct i2c_dev_desc * i2cdev ;
1658
1677
int ret ;
1659
1678
@@ -1685,34 +1704,6 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
1685
1704
goto err_detach_devs ;
1686
1705
}
1687
1706
}
1688
- list_for_each_entry (i3cboardinfo , & master -> boardinfo .i3c , node ) {
1689
- struct i3c_device_info info = {
1690
- .static_addr = i3cboardinfo -> static_addr ,
1691
- };
1692
-
1693
- if (i3cboardinfo -> init_dyn_addr ) {
1694
- status = i3c_bus_get_addr_slot_status (& master -> bus ,
1695
- i3cboardinfo -> init_dyn_addr );
1696
- if (status != I3C_ADDR_SLOT_FREE ) {
1697
- ret = - EBUSY ;
1698
- goto err_detach_devs ;
1699
- }
1700
- }
1701
-
1702
- i3cdev = i3c_master_alloc_i3c_dev (master , & info );
1703
- if (IS_ERR (i3cdev )) {
1704
- ret = PTR_ERR (i3cdev );
1705
- goto err_detach_devs ;
1706
- }
1707
-
1708
- i3cdev -> boardinfo = i3cboardinfo ;
1709
-
1710
- ret = i3c_master_attach_i3c_dev (master , i3cdev );
1711
- if (ret ) {
1712
- i3c_master_free_i3c_dev (i3cdev );
1713
- goto err_detach_devs ;
1714
- }
1715
- }
1716
1707
1717
1708
/*
1718
1709
* Now execute the controller specific ->bus_init() routine, which
@@ -1749,11 +1740,43 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
1749
1740
goto err_bus_cleanup ;
1750
1741
1751
1742
/*
1752
- * Pre-assign dynamic address and retrieve device information if
1753
- * needed.
1743
+ * Reserve init_dyn_addr first, and then try to pre-assign dynamic
1744
+ * address and retrieve device information if needed.
1745
+ * In case pre-assign dynamic address fails, setting dynamic address to
1746
+ * the requested init_dyn_addr is retried after DAA is done in
1747
+ * i3c_master_add_i3c_dev_locked().
1754
1748
*/
1755
- i3c_bus_for_each_i3cdev (& master -> bus , i3cdev )
1756
- i3c_master_pre_assign_dyn_addr (i3cdev );
1749
+ list_for_each_entry (i3cboardinfo , & master -> boardinfo .i3c , node ) {
1750
+
1751
+ /*
1752
+ * We don't reserve a dynamic address for devices that
1753
+ * don't explicitly request one.
1754
+ */
1755
+ if (!i3cboardinfo -> init_dyn_addr )
1756
+ continue ;
1757
+
1758
+ ret = i3c_bus_get_addr_slot_status (& master -> bus ,
1759
+ i3cboardinfo -> init_dyn_addr );
1760
+ if (ret != I3C_ADDR_SLOT_FREE ) {
1761
+ ret = - EBUSY ;
1762
+ goto err_rstdaa ;
1763
+ }
1764
+
1765
+ i3c_bus_set_addr_slot_status (& master -> bus ,
1766
+ i3cboardinfo -> init_dyn_addr ,
1767
+ I3C_ADDR_SLOT_I3C_DEV );
1768
+
1769
+ /*
1770
+ * Only try to create/attach devices that have a static
1771
+ * address. Other devices will be created/attached when
1772
+ * DAA happens, and the requested dynamic address will
1773
+ * be set using SETNEWDA once those devices become
1774
+ * addressable.
1775
+ */
1776
+
1777
+ if (i3cboardinfo -> static_addr )
1778
+ i3c_master_early_i3c_dev_add (master , i3cboardinfo );
1779
+ }
1757
1780
1758
1781
ret = i3c_master_do_daa (master );
1759
1782
if (ret )
@@ -1782,6 +1805,21 @@ static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
1782
1805
i3c_master_detach_free_devs (master );
1783
1806
}
1784
1807
1808
+ static void i3c_master_attach_boardinfo (struct i3c_dev_desc * i3cdev )
1809
+ {
1810
+ struct i3c_master_controller * master = i3cdev -> common .master ;
1811
+ struct i3c_dev_boardinfo * i3cboardinfo ;
1812
+
1813
+ list_for_each_entry (i3cboardinfo , & master -> boardinfo .i3c , node ) {
1814
+ if (i3cdev -> info .pid != i3cboardinfo -> pid )
1815
+ continue ;
1816
+
1817
+ i3cdev -> boardinfo = i3cboardinfo ;
1818
+ i3cdev -> info .static_addr = i3cboardinfo -> static_addr ;
1819
+ return ;
1820
+ }
1821
+ }
1822
+
1785
1823
static struct i3c_dev_desc *
1786
1824
i3c_master_search_i3c_dev_duplicate (struct i3c_dev_desc * refdev )
1787
1825
{
@@ -1837,10 +1875,10 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
1837
1875
if (ret )
1838
1876
goto err_detach_dev ;
1839
1877
1878
+ i3c_master_attach_boardinfo (newdev );
1879
+
1840
1880
olddev = i3c_master_search_i3c_dev_duplicate (newdev );
1841
1881
if (olddev ) {
1842
- newdev -> boardinfo = olddev -> boardinfo ;
1843
- newdev -> info .static_addr = olddev -> info .static_addr ;
1844
1882
newdev -> dev = olddev -> dev ;
1845
1883
if (newdev -> dev )
1846
1884
newdev -> dev -> desc = newdev ;
0 commit comments