Merge tag 'i3c/for-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Sep 2023 22:59:57 +0000 (15:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Sep 2023 22:59:57 +0000 (15:59 -0700)
Pull i3c updates from Alexandre Belloni:
 "Core:
   - Fix SETDASA when static and dynamic adress are equal
   - Fix cmd_v1 DAA exit criteria

  Drivers:
   - svc: allow probing without any device"

* tag 'i3c/for-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux:
  i3c: master: svc: fix probe failure when no i3c device exist
  i3c: master: Fix SETDASA process
  dt-bindings: i3c: Fix description for assigned-address
  i3c: master: svc: Describe member 'saved_regs'
  i3c: master: svc: Do not check for 0 return after calling platform_get_irq()
  i3c/master: cmd_v1: Fix the exit criteria for the daa procedure
  i3c: Explicitly include correct DT includes

Documentation/devicetree/bindings/i3c/i3c.yaml
drivers/i3c/master.c
drivers/i3c/master/ast2600-i3c-master.c
drivers/i3c/master/i3c-master-cdns.c
drivers/i3c/master/mipi-i3c-hci/cmd_v1.c
drivers/i3c/master/svc-i3c-master.c

index fdb4212..ab69f41 100644 (file)
@@ -135,9 +135,10 @@ patternProperties:
         minimum: 0x1
         maximum: 0xff
         description: |
-          Dynamic address to be assigned to this device. This property is only
-          valid if the I3C device has a static address (first cell of the reg
-          property != 0).
+          Dynamic address to be assigned to this device. In case static address is
+          present (first cell of the reg property != 0), this address is assigned
+          through SETDASA. If static address is not present, this address is assigned
+          through SETNEWDA after assigning a temporary address via ENTDAA.
 
     required:
       - reg
@@ -163,12 +164,18 @@ examples:
             pagesize = <0x8>;
         };
 
-        /* I3C device with a static I2C address. */
+        /* I3C device with a static I2C address and assigned address. */
         thermal_sensor: sensor@68,39200144004 {
             reg = <0x68 0x392 0x144004>;
             assigned-address = <0xa>;
         };
 
+        /* I3C device with only assigned address. */
+        pressure_sensor: sensor@0,39200124004 {
+            reg = <0x0 0x392 0x124000>;
+            assigned-address = <0xc>;
+        };
+
         /*
          * I3C device without a static I2C address but requiring
          * resources described in the DT.
index 08aeb69..87283e4 100644 (file)
@@ -1308,7 +1308,11 @@ static int i3c_master_get_i3c_addrs(struct i3c_dev_desc *dev)
        if (dev->info.static_addr) {
                status = i3c_bus_get_addr_slot_status(&master->bus,
                                                      dev->info.static_addr);
-               if (status != I3C_ADDR_SLOT_FREE)
+               /* Since static address and assigned dynamic address can be
+                * equal, allow this case to pass.
+                */
+               if (status != I3C_ADDR_SLOT_FREE &&
+                   dev->info.static_addr != dev->boardinfo->init_dyn_addr)
                        return -EBUSY;
 
                i3c_bus_set_addr_slot_status(&master->bus,
index 09ed19d..01a47d3 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 
index 01610fa..49551db 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
-#include <linux/of_device.h>
 
 #define DEV_ID                         0x0
 #define DEV_ID_I3C_MASTER              0x5034
index d97c317..6a781f8 100644 (file)
@@ -339,7 +339,7 @@ static int hci_cmd_v1_daa(struct i3c_hci *hci)
                        break;
                }
                if (RESP_STATUS(xfer[0].response) == RESP_ERR_NACK &&
-                   RESP_STATUS(xfer[0].response) == 1) {
+                   RESP_DATA_LENGTH(xfer->response) == 1) {
                        ret = 0;  /* no more devices to be assigned */
                        break;
                }
index 0d63b73..8f8295a 100644 (file)
@@ -156,6 +156,7 @@ struct svc_i3c_regs_save {
  * @base: I3C master controller
  * @dev: Corresponding device
  * @regs: Memory mapping
+ * @saved_regs: Volatile values for PM operations
  * @free_slots: Bit array of available slots
  * @addrs: Array containing the dynamic addresses of each attached device
  * @descs: Array of descriptors, one per attached device
@@ -789,6 +790,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
                                 */
                                break;
                        } else if (SVC_I3C_MSTATUS_NACKED(reg)) {
+                               /* No I3C devices attached */
+                               if (dev_nb == 0)
+                                       break;
+
                                /*
                                 * A slave device nacked the address, this is
                                 * allowed only once, DAA will be stopped and
@@ -1263,11 +1268,17 @@ static int svc_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
 {
        struct svc_i3c_master *master = to_svc_i3c_master(m);
        bool broadcast = cmd->id < 0x80;
+       int ret;
 
        if (broadcast)
-               return svc_i3c_master_send_bdcast_ccc_cmd(master, cmd);
+               ret = svc_i3c_master_send_bdcast_ccc_cmd(master, cmd);
        else
-               return svc_i3c_master_send_direct_ccc_cmd(master, cmd);
+               ret = svc_i3c_master_send_direct_ccc_cmd(master, cmd);
+
+       if (ret)
+               cmd->err = I3C_ERROR_M2;
+
+       return ret;
 }
 
 static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
@@ -1518,8 +1529,8 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
                return PTR_ERR(master->sclk);
 
        master->irq = platform_get_irq(pdev, 0);
-       if (master->irq <= 0)
-               return -ENOENT;
+       if (master->irq < 0)
+               return master->irq;
 
        master->dev = dev;