driver->remove(i3cdev);
}
-const struct bus_type i3c_bus_type = {
- .name = "i3c",
- .match = i3c_device_match,
- .probe = i3c_device_probe,
- .remove = i3c_device_remove,
-};
-EXPORT_SYMBOL_GPL(i3c_bus_type);
-
static enum i3c_addr_slot_status
i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
{
{
struct i3c_master_controller *master = container_of(work, typeof(*master), hj_work);
- i3c_master_do_daa(master);
+ if (!master->shutting_down)
+ i3c_master_do_daa(master);
}
static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable)
i3c_bus_maintenance_lock(&master->bus);
- if (enable)
+ if (master->shutting_down)
+ ret = -ENODEV;
+ else if (enable)
ret = master->ops->enable_hotjoin(master);
else
ret = master->ops->disable_hotjoin(master);
.groups = i3c_masterdev_groups,
};
+static void i3c_master_shutdown(struct i3c_master_controller *master)
+{
+ i3c_bus_maintenance_lock(&master->bus);
+ master->shutting_down = true;
+ i3c_bus_maintenance_unlock(&master->bus);
+
+ cancel_work_sync(&master->hj_work);
+}
+
+static void i3c_device_shutdown(struct device *dev)
+{
+ if (dev->type == &i3c_masterdev_type)
+ i3c_master_shutdown(dev_to_i3cmaster(dev));
+}
+
+const struct bus_type i3c_bus_type = {
+ .name = "i3c",
+ .match = i3c_device_match,
+ .probe = i3c_device_probe,
+ .remove = i3c_device_remove,
+ .shutdown = i3c_device_shutdown,
+};
+EXPORT_SYMBOL_GPL(i3c_bus_type);
+
static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
unsigned long max_i2c_scl_rate)
{
i3c_bus_maintenance_lock(&master->bus);
- if (rstdaa)
- rstret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
-
- ret = master->ops->do_daa(master);
+ if (master->shutting_down) {
+ ret = -ENODEV;
+ } else {
+ if (rstdaa)
+ rstret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
+ ret = master->ops->do_daa(master);
+ }
i3c_bus_maintenance_unlock(&master->bus);
void i3c_master_unregister(struct i3c_master_controller *master)
{
i3c_bus_notify(&master->bus, I3C_NOTIFY_BUS_REMOVE);
- cancel_work_sync(&master->hj_work);
+ i3c_master_shutdown(master);
if (master->ops->set_dev_nack_retry)
device_remove_file(&master->dev, &dev_attr_dev_nack_retry_count);