diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 0436916..b398d77 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -449,6 +449,46 @@ static ssize_t mode_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(mode);
 
+static ssize_t
+mastership_show(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct i3c_master_controller *master = dev_to_i3cmaster(dev);
+	ssize_t ret;
+
+	if (master->secondary)
+		ret = sprintf(buf, "Secondary Master\n");
+	else
+		ret = sprintf(buf, "Master\n");
+
+	return ret;
+}
+
+static ssize_t
+mastership_store(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct i3c_master_controller *master = dev_to_i3cmaster(dev);
+	struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
+
+	if (i3cbus->cur_master == master->this) {
+		dev_err(dev, "I'm current mater.");
+		return count;
+	}
+
+	if (!master->ops->request_mastership) {
+		dev_err(dev, "mastership_request not supported.");
+		return count;
+	}
+
+	if (master->ops->request_mastership(master))
+		dev_err(dev, "mastership_request failed");
+	else
+		dev_err(dev, "mastership_request success");
+
+	return count;
+}
+static DEVICE_ATTR_RW(mastership);
+
 static ssize_t current_master_show(struct device *dev,
 				   struct device_attribute *da,
 				   char *buf)
@@ -457,8 +497,11 @@ static ssize_t current_master_show(struct device *dev,
 	ssize_t ret;
 
 	i3c_bus_normaluse_lock(i3cbus);
-	ret = sprintf(buf, "%d-%llx\n", i3cbus->id,
-		      i3cbus->cur_master->info.pid);
+	if (i3cbus->cur_master)
+		ret = sprintf(buf, "%d-%llx\n", i3cbus->id,
+			      i3cbus->cur_master->info.pid);
+	else
+		ret = sprintf(buf, "Not Current Master\n");
 	i3c_bus_normaluse_unlock(i3cbus);
 
 	return ret;
@@ -497,6 +540,7 @@ static DEVICE_ATTR_RO(i2c_scl_frequency);
 
 static struct attribute *i3c_masterdev_attrs[] = {
 	&dev_attr_mode.attr,
+	&dev_attr_mastership.attr,
 	&dev_attr_current_master.attr,
 	&dev_attr_i3c_scl_frequency.attr,
 	&dev_attr_i2c_scl_frequency.attr,
@@ -854,6 +898,53 @@ int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr,
 EXPORT_SYMBOL_GPL(i3c_master_enec_locked);
 
 /**
+ * i3c_master_getaccmst_locked() - send an GETACCMST CCC command
+ * @master: master used to send frames on the bus
+ * @addr: a valid I3C slave address
+ *
+ * Sends an GETACCMST CCC command to offer bus Mastership to an
+ * I3C Secondary Master.
+ *
+ * This function must be called with the bus lock held in write mode.
+ *
+ * Return: 0 in case of success, a positive I3C error code if the error is
+ * one of the official Mx error codes, and a negative error code otherwise.
+ */
+int i3c_master_getaccmst_locked(struct i3c_master_controller *master, u8 addr)
+{
+	enum i3c_addr_slot_status addrstat;
+	struct i3c_ccc_getaccmst *accmst;
+	struct i3c_ccc_cmd_dest dest;
+	struct i3c_ccc_cmd cmd;
+	int ret;
+
+	if (!master)
+		return -EINVAL;
+
+	addrstat = i3c_bus_get_addr_slot_status(&master->bus, addr);
+	if (addr == I3C_BROADCAST_ADDR || addrstat != I3C_ADDR_SLOT_I3C_DEV)
+		return -EINVAL;
+
+	accmst = i3c_ccc_cmd_dest_init(&dest, addr, sizeof(*accmst));
+	if (!accmst)
+		return -ENOMEM;
+
+	i3c_ccc_cmd_init(&cmd, true, I3C_CCC_GETACCMST, &dest, 1);
+
+	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
+	if (ret)
+		goto out;
+
+	if (accmst->newmaster >> 1 != addr)
+		ret = -EIO;
+out:
+	i3c_ccc_cmd_dest_cleanup(&dest);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_master_getaccmst_locked);
+
+/**
  * i3c_master_defslvs_locked() - send a DEFSLVS CCC command
  * @master: master used to send frames on the bus
  *
@@ -1542,8 +1633,7 @@ int i3c_master_set_info(struct i3c_master_controller *master,
 	if (!i3c_bus_dev_addr_is_avail(&master->bus, info->dyn_addr))
 		return -EINVAL;
 
-	if (I3C_BCR_DEVICE_ROLE(info->bcr) == I3C_BCR_I3C_MASTER &&
-	    master->secondary)
+	if (I3C_BCR_DEVICE_ROLE(info->bcr) != I3C_BCR_I3C_MASTER)
 		return -EINVAL;
 
 	if (master->this)
@@ -2381,6 +2471,81 @@ static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops)
 	return 0;
 }
 
+int i3c_sec_master_bus_init(struct i3c_master_controller *master)
+{
+	unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
+	struct i3c_bus *i3cbus = i3c_master_get_bus(master);
+	enum i3c_bus_mode mode = i3cbus->mode;
+	struct i3c_defslvs_info *defslvsinfo;
+	int ret = 0;
+
+	if (master->init_done)
+		return -EINVAL;
+
+	list_for_each_entry(defslvsinfo, &master->defslvs, node) {
+		if (defslvsinfo->slave.dyn_addr)
+			continue;
+
+		switch (defslvsinfo->slave.lvr & I3C_LVR_I2C_INDEX_MASK) {
+		case I3C_LVR_I2C_INDEX(0):
+			if (mode < I3C_BUS_MODE_MIXED_FAST)
+				mode = I3C_BUS_MODE_MIXED_FAST;
+			break;
+		case I3C_LVR_I2C_INDEX(1):
+		case I3C_LVR_I2C_INDEX(2):
+			if (mode < I3C_BUS_MODE_MIXED_SLOW)
+				mode = I3C_BUS_MODE_MIXED_SLOW;
+			break;
+		default:
+			ret = -EINVAL;
+			goto err_put_dev;
+		}
+		if (defslvsinfo->slave.lvr & I3C_LVR_I2C_FM_MODE)
+			i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
+	}
+
+	ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
+	if (ret)
+		goto err_put_dev;
+
+	/*
+	 * Now execute the controller specific ->bus_init() routine, which
+	 * might configure its internal logic to match the bus limitations.
+	 */
+	ret = master->ops->bus_init(master);
+	if (ret)
+		goto err_put_dev;
+
+	/*
+	 * The master device should have been instantiated in ->bus_init(),
+	 * complain if this was not the case.
+	 */
+	if (!master->this) {
+		dev_err(&master->dev,
+			"master_set_info() was not called in ->bus_init()\n");
+		ret = -EINVAL;
+		goto err_put_dev;
+	}
+
+	ret = device_add(&master->dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+	 * through the I2C subsystem.
+	 */
+	ret = i3c_master_i2c_adapter_init(master);
+	if (ret)
+		goto err_put_dev;
+
+	master->init_done = true;
+
+err_put_dev:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_sec_master_bus_init);
+
 /**
  * i3c_master_register() - register an I3C master
  * @master: master used to send frames on the bus
@@ -2413,10 +2578,6 @@ int i3c_master_register(struct i3c_master_controller *master,
 	struct i2c_dev_boardinfo *i2cbi;
 	int ret;
 
-	/* We do not support secondary masters yet. */
-	if (secondary)
-		return -ENOTSUPP;
-
 	ret = i3c_master_check_ops(ops);
 	if (ret)
 		return ret;
@@ -2430,6 +2591,7 @@ int i3c_master_register(struct i3c_master_controller *master,
 	master->secondary = secondary;
 	INIT_LIST_HEAD(&master->boardinfo.i2c);
 	INIT_LIST_HEAD(&master->boardinfo.i3c);
+	INIT_LIST_HEAD(&master->defslvs);
 
 	ret = i3c_bus_init(i3cbus);
 	if (ret)
@@ -2475,6 +2637,9 @@ int i3c_master_register(struct i3c_master_controller *master,
 		goto err_put_dev;
 	}
 
+	if (secondary)
+		return 0;
+
 	ret = i3c_master_bus_init(master);
 	if (ret)
 		goto err_put_dev;
@@ -2547,6 +2712,11 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
 	if (!master || !xfers)
 		return -EINVAL;
 
+	if (master->bus.cur_master != master->this) {
+		master->ops->request_mastership(master);
+		return -EBUSY;
+	}
+
 	if (!master->ops->priv_xfers)
 		return -ENOTSUPP;
 
@@ -2638,6 +2808,185 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
 	dev->ibi = NULL;
 }
 
+static const char *const i3c_dr_modes[] = {
+	[I3C_DR_MODE_MASTER]		= "master",
+	[I3C_DR_MODE_SEC_MASTER]	= "sec-master",
+	[I3C_DR_MODE_SLAVE]		= "slave",
+};
+
+static enum i3c_dr_mode i3c_get_dr_mode_from_string(const char *str)
+{
+	int ret;
+
+	ret = match_string(i3c_dr_modes, ARRAY_SIZE(i3c_dr_modes), str);
+	return (ret < 0) ? I3C_DR_MODE_MASTER : ret;
+}
+
+enum i3c_dr_mode i3c_get_dr_mode(struct device *dev)
+{
+	const char *dr_mode;
+	int err;
+
+	err = device_property_read_string(dev, "dr-mode", &dr_mode);
+	if (err < 0)
+		return I3C_DR_MODE_MASTER;
+
+	return i3c_get_dr_mode_from_string(dr_mode);
+}
+EXPORT_SYMBOL_GPL(i3c_get_dr_mode);
+
+int i3c_sec_master_request_mastership(struct i3c_master_controller *master)
+{
+	int ret;
+
+	i3c_bus_normaluse_lock(&master->bus);
+	ret = master->ops->request_mastership(master);
+	i3c_bus_normaluse_unlock(&master->bus);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_sec_master_request_mastership);
+
+int i3c_master_deliver_mastership(struct i3c_master_controller *master, u8 addr)
+{
+	struct i3c_dev_desc *dev;
+	int ret;
+
+	i3c_bus_normaluse_lock(&master->bus);
+	i3c_bus_for_each_i3cdev(&master->bus, dev) {
+		if (dev->ibi) {
+			mutex_lock(&dev->ibi_lock);
+			i3c_dev_disable_ibi_locked(dev);
+			mutex_unlock(&dev->ibi_lock);
+		}
+	}
+	i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
+				I3C_CCC_EVENT_MR | I3C_CCC_EVENT_HJ);
+
+	ret = master->ops->deliver_mastership(master, addr);
+	i3c_bus_normaluse_unlock(&master->bus);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_master_deliver_mastership);
+
+int defslvs_populate_i3c_bus(struct i3c_master_controller *master,
+			     struct i3c_ccc_dev_desc defslvs)
+{
+	struct i3c_defslvs_info *defslvsinfo;
+	struct device *dev = &master->dev;
+
+	i3c_bus_maintenance_lock(&master->bus);
+	defslvsinfo = devm_kzalloc(dev, sizeof(*defslvsinfo), GFP_KERNEL);
+	if (!defslvsinfo)
+		return -ENOMEM;
+
+	defslvsinfo->slave = defslvs;
+
+	list_add_tail(&defslvsinfo->node, &master->defslvs);
+
+	i3c_bus_maintenance_unlock(&master->bus);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(defslvs_populate_i3c_bus);
+
+static void i3c_master_add_new_defslvs(struct i3c_master_controller *master)
+{
+	struct i3c_defslvs_info *defslvsinfo;
+
+	list_for_each_entry(defslvsinfo, &master->defslvs, node) {
+		/* TODO: add i2c devices to the bus */
+		if (!defslvsinfo->slave.dyn_addr)
+			continue;
+
+		if (defslvsinfo->slave.dyn_addr == master->this->info.dyn_addr)
+			continue;
+
+		if (!i3c_bus_dev_addr_is_avail(&master->bus,
+					       defslvsinfo->slave.dyn_addr))
+			continue;
+
+		i3c_master_add_i3c_dev_locked(master, defslvsinfo->slave.dyn_addr);
+	}
+
+	while (!list_empty(&master->defslvs)) {
+		defslvsinfo = list_first_entry(&master->defslvs,
+					       struct i3c_defslvs_info, node);
+		list_del(&defslvsinfo->node);
+	}
+}
+
+int i3c_master_switch_operation_mode(struct i3c_master_controller *master,
+				     bool secondary)
+{
+	struct i3c_dev_desc *dev;
+	int ret;
+
+	if (master->secondary == secondary)
+		return -EEXIST;
+
+	/* TODO: get the current master information */
+	if (secondary)
+		master->bus.cur_master = NULL;
+	else
+		master->bus.cur_master = master->this;
+
+	if (!master->init_done && !secondary)
+		i3c_sec_master_bus_init(master);
+
+	master->secondary = secondary;
+
+	dev_info(&master->dev, "changing to %s\n",
+		 master->secondary ? "Sec Master" : "Master");
+
+	/* TODO: Analyse the use of maintenan_lock for everything */
+	if (!list_empty(&master->defslvs) && !secondary) {
+		i3c_bus_maintenance_lock(&master->bus);
+		i3c_master_add_new_defslvs(master);
+		i3c_bus_maintenance_unlock(&master->bus);
+
+		i3c_bus_normaluse_lock(&master->bus);
+		i3c_master_register_new_i3c_devs(master);
+		i3c_bus_normaluse_unlock(&master->bus);
+	}
+
+	if (!secondary) {
+		i3c_bus_normaluse_lock(&master->bus);
+		i3c_bus_for_each_i3cdev(&master->bus, dev) {
+			if (dev->ibi) {
+				mutex_lock(&dev->ibi_lock);
+				ret = i3c_dev_enable_ibi_locked(dev);
+				if (ret)
+					dev_err(&master->dev,
+						"Failed to re-enable IBI on device %d-%llx",
+						master->bus.id, dev->info.pid);
+				mutex_unlock(&dev->ibi_lock);
+				}
+		}
+
+		/* TODO: Enable MR only for the elegible devices */
+		i3c_master_enec_locked(master, I3C_BROADCAST_ADDR,
+					I3C_CCC_EVENT_MR | I3C_CCC_EVENT_HJ);
+		i3c_bus_normaluse_unlock(&master->bus);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(i3c_master_switch_operation_mode);
+
+int i3c_for_each_dev(void *data, int (*fn)(struct device *, void *))
+{
+	int res;
+
+	mutex_lock(&i3c_core_lock);
+	res = bus_for_each_dev(&i3c_bus_type, NULL, data, fn);
+	mutex_unlock(&i3c_core_lock);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(i3c_for_each_dev);
+
 static int __init i3c_init(void)
 {
 	return bus_register(&i3c_bus_type);
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 9cb39d9..09bd99c 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -426,6 +426,8 @@ struct i3c_bus {
  *		      for a future IBI
  *		      This method is mandatory only if ->request_ibi is not
  *		      NULL.
+ * @request_mastership: Request mastership.
+ * @deliver_mastership: Deliver mastership
  */
 struct i3c_master_controller_ops {
 	int (*bus_init)(struct i3c_master_controller *master);
@@ -452,6 +454,21 @@ struct i3c_master_controller_ops {
 	int (*disable_ibi)(struct i3c_dev_desc *dev);
 	void (*recycle_ibi_slot)(struct i3c_dev_desc *dev,
 				 struct i3c_ibi_slot *slot);
+	int (*request_mastership)(struct i3c_master_controller *master);
+	int (*deliver_mastership)(struct i3c_master_controller *master,
+				  u8 addr);
+};
+
+/**
+ * struct i3c_defslvs_info - defslvs information object
+ * @node: used to insert the defslvs object in the  list
+ * @slave: I3C/I2C device descriptor used for DEFSLVS
+ *
+ * This structure is used to hold defslvs information on Secondary Master.
+ */
+struct i3c_defslvs_info {
+	struct list_head node;
+	struct i3c_ccc_dev_desc slave;
 };
 
 /**
@@ -468,6 +485,7 @@ struct i3c_master_controller_ops {
  * @boardinfo.i3c: list of I3C  boardinfo objects
  * @boardinfo.i2c: list of I2C boardinfo objects
  * @boardinfo: board-level information attached to devices connected on the bus
+ * @defslvs: List of defslvs objects
  * @bus: I3C bus exposed by this master
  * @wq: workqueue used to execute IBI handlers. Can also be used by master
  *	drivers if they need to postpone operations that need to take place
@@ -491,6 +509,7 @@ struct i3c_master_controller {
 		struct list_head i3c;
 		struct list_head i2c;
 	} boardinfo;
+	struct list_head defslvs;
 	struct i3c_bus bus;
 	struct workqueue_struct *wq;
 };
@@ -525,6 +544,7 @@ int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr,
 			    u8 evts);
 int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr,
 			   u8 evts);
+int i3c_master_getaccmst_locked(struct i3c_master_controller *master, u8 addr);
 int i3c_master_entdaa_locked(struct i3c_master_controller *master);
 int i3c_master_defslvs_locked(struct i3c_master_controller *master);
 
@@ -652,4 +672,23 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot);
 
 struct i3c_ibi_slot *i3c_master_get_free_ibi_slot(struct i3c_dev_desc *dev);
 
+enum i3c_dr_mode {
+	I3C_DR_MODE_MASTER,
+	I3C_DR_MODE_SEC_MASTER,
+	I3C_DR_MODE_SLAVE,
+};
+
+enum i3c_dr_mode i3c_get_dr_mode(struct device *dev);
+
+int i3c_master_switch_operation_mode(struct i3c_master_controller *master,
+				     bool secondary);
+
+int i3c_sec_master_request_mastership(struct i3c_master_controller *master);
+int i3c_master_deliver_mastership(struct i3c_master_controller *master,
+				  u8 addr);
+
+int i3c_sec_master_bus_init(struct i3c_master_controller *master);
+int defslvs_populate_i3c_bus(struct i3c_master_controller *master,
+			     struct i3c_ccc_dev_desc defslvs);
+
 #endif /* I3C_MASTER_H */
