Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96407298 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ic3 updates from Boris Brezillon:

 - Drop support for 10-bit I2C addresses

 - Add support for limited bus mode

 - Fix the Cadence DT binding doc

 - Use struct_size() to allocate a DEFSLVS packet

* tag 'i3c/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux:
  i3c: master: Use struct_size() helper
  dt-bindings: i3c: cdns: Use correct cells for I2C device
  i3c: dw: add limited bus mode support
  i3c: add mixed limited bus mode
  i3c: fix i2c and i3c scl rate by bus mode
  dt-bindings: i3c: Document dropped support for I2C 10 bit devices
  i3c: Drop support for I2C 10 bit addresing
parents 8a3367cc ede20015
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -38,6 +38,6 @@ Example:

		nunchuk: nunchuk@52 {
			compatible = "nintendo,nunchuk";
			reg = <0x52 0x80000010 0>;
			reg = <0x52 0x0 0x10>;
		};
	};
+3 −1
Original line number Diff line number Diff line
@@ -39,7 +39,9 @@ valid here, but several new properties have been added.
New constraint on existing properties:
--------------------------------------
- reg: contains 3 cells
  + first cell : still encoding the I2C address
  + first cell : still encoding the I2C address. 10 bit addressing is not
    supported. Devices with 10 bit address can't be properly passed through
    DEFSLVS command.

  + second cell: shall be 0

+59 −23
Original line number Diff line number Diff line
@@ -91,6 +91,12 @@ void i3c_bus_normaluse_unlock(struct i3c_bus *bus)
	up_read(&bus->lock);
}

static struct i3c_master_controller *
i3c_bus_to_i3c_master(struct i3c_bus *i3cbus)
{
	return container_of(i3cbus, struct i3c_master_controller, bus);
}

static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev)
{
	return container_of(dev, struct i3c_master_controller, dev);
@@ -464,6 +470,7 @@ static int i3c_bus_init(struct i3c_bus *i3cbus)
static const char * const i3c_bus_mode_strings[] = {
	[I3C_BUS_MODE_PURE] = "pure",
	[I3C_BUS_MODE_MIXED_FAST] = "mixed-fast",
	[I3C_BUS_MODE_MIXED_LIMITED] = "mixed-limited",
	[I3C_BUS_MODE_MIXED_SLOW] = "mixed-slow",
};

@@ -565,20 +572,39 @@ static const struct device_type i3c_masterdev_type = {
	.groups	= i3c_masterdev_groups,
};

int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode)
int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
		     unsigned long max_i2c_scl_rate)
{
	struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);

	i3cbus->mode = mode;

	switch (i3cbus->mode) {
	case I3C_BUS_MODE_PURE:
		if (!i3cbus->scl_rate.i3c)
			i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;

	if (!i3cbus->scl_rate.i2c) {
		if (i3cbus->mode == I3C_BUS_MODE_MIXED_SLOW)
			i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE;
		else
			i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
		break;
	case I3C_BUS_MODE_MIXED_FAST:
	case I3C_BUS_MODE_MIXED_LIMITED:
		if (!i3cbus->scl_rate.i3c)
			i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
		if (!i3cbus->scl_rate.i2c)
			i3cbus->scl_rate.i2c = max_i2c_scl_rate;
		break;
	case I3C_BUS_MODE_MIXED_SLOW:
		if (!i3cbus->scl_rate.i2c)
			i3cbus->scl_rate.i2c = max_i2c_scl_rate;
		if (!i3cbus->scl_rate.i3c ||
		    i3cbus->scl_rate.i3c > i3cbus->scl_rate.i2c)
			i3cbus->scl_rate.i3c = i3cbus->scl_rate.i2c;
		break;
	default:
		return -EINVAL;
	}

	dev_dbg(&master->dev, "i2c-scl = %ld Hz i3c-scl = %ld Hz\n",
		i3cbus->scl_rate.i2c, i3cbus->scl_rate.i3c);

	/*
	 * I3C/I2C frequency may have been overridden, check that user-provided
	 * values are not exceeding max possible frequency.
@@ -924,9 +950,8 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
		ndevs++;

	defslvs = i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR,
					sizeof(*defslvs) +
					((ndevs - 1) *
					 sizeof(struct i3c_ccc_dev_desc)));
					struct_size(defslvs, slaves,
						    ndevs - 1));
	if (!defslvs)
		return -ENOMEM;

@@ -1963,12 +1988,19 @@ of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
	if (ret)
		return ret;

	/*
	 * The I3C Specification does not clearly say I2C devices with 10-bit
	 * address are supported. These devices can't be passed properly through
	 * DEFSLVS command.
	 */
	if (boardinfo->base.flags & I2C_CLIENT_TEN) {
		dev_err(&master->dev, "I2C device with 10 bit address not supported.");
		return -ENOTSUPP;
	}

	/* LVR is encoded in reg[2]. */
	boardinfo->lvr = reg[2];

	if (boardinfo->lvr & I3C_LVR_I2C_FM_MODE)
		master->bus.scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE;

	list_add_tail(&boardinfo->node, &master->boardinfo.i2c);
	of_node_get(node);

@@ -2111,16 +2143,14 @@ static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap,
	return ret ? ret : nxfers;
}

static u32 i3c_master_i2c_functionalities(struct i2c_adapter *adap)
static u32 i3c_master_i2c_funcs(struct i2c_adapter *adapter)
{
	struct i3c_master_controller *master = i2c_adapter_to_i3c_master(adap);

	return master->ops->i2c_funcs(master);
	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
}

static const struct i2c_algorithm i3c_master_i2c_algo = {
	.master_xfer = i3c_master_i2c_adapter_xfer,
	.functionality = i3c_master_i2c_functionalities,
	.functionality = i3c_master_i2c_funcs,
};

static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
@@ -2379,8 +2409,7 @@ EXPORT_SYMBOL_GPL(i3c_generic_ibi_recycle_slot);
static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops)
{
	if (!ops || !ops->bus_init || !ops->priv_xfers ||
	    !ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers ||
	    !ops->i2c_funcs)
	    !ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers)
		return -EINVAL;

	if (ops->request_ibi &&
@@ -2417,6 +2446,7 @@ int i3c_master_register(struct i3c_master_controller *master,
			const struct i3c_master_controller_ops *ops,
			bool secondary)
{
	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 = I3C_BUS_MODE_PURE;
	struct i2c_dev_boardinfo *i2cbi;
@@ -2458,6 +2488,9 @@ int i3c_master_register(struct i3c_master_controller *master,
				mode = I3C_BUS_MODE_MIXED_FAST;
			break;
		case I3C_LVR_I2C_INDEX(1):
			if (mode < I3C_BUS_MODE_MIXED_LIMITED)
				mode = I3C_BUS_MODE_MIXED_LIMITED;
			break;
		case I3C_LVR_I2C_INDEX(2):
			if (mode < I3C_BUS_MODE_MIXED_SLOW)
				mode = I3C_BUS_MODE_MIXED_SLOW;
@@ -2466,9 +2499,12 @@ int i3c_master_register(struct i3c_master_controller *master,
			ret = -EINVAL;
			goto err_put_dev;
		}

		if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)
			i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
	}

	ret = i3c_bus_set_mode(i3cbus, mode);
	ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
	if (ret)
		goto err_put_dev;

+1 −6
Original line number Diff line number Diff line
@@ -599,6 +599,7 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m)

	switch (bus->mode) {
	case I3C_BUS_MODE_MIXED_FAST:
	case I3C_BUS_MODE_MIXED_LIMITED:
		ret = dw_i2c_clk_cfg(master);
		if (ret)
			return ret;
@@ -1060,11 +1061,6 @@ static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
	kfree(data);
}

static u32 dw_i3c_master_i2c_funcs(struct i3c_master_controller *m)
{
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}

static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id)
{
	struct dw_i3c_master *master = dev_id;
@@ -1099,7 +1095,6 @@ static const struct i3c_master_controller_ops dw_mipi_i3c_ops = {
	.attach_i2c_dev = dw_i3c_master_attach_i2c_dev,
	.detach_i2c_dev = dw_i3c_master_detach_i2c_dev,
	.i2c_xfers = dw_i3c_master_i2c_xfers,
	.i2c_funcs = dw_i3c_master_i2c_funcs,
};

static int dw_i3c_probe(struct platform_device *pdev)
+1 −9
Original line number Diff line number Diff line
@@ -864,11 +864,6 @@ static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
	return ret;
}

static u32 cdns_i3c_master_i2c_funcs(struct i3c_master_controller *m)
{
	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
}

struct cdns_i3c_i2c_dev_data {
	u16 id;
	s16 ibi;
@@ -1010,9 +1005,7 @@ static int cdns_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
	master->free_rr_slots &= ~BIT(slot);
	i2c_dev_set_master_data(dev, data);

	writel(prepare_rr0_dev_address(dev->boardinfo->base.addr) |
	       (dev->boardinfo->base.flags & I2C_CLIENT_TEN ?
		DEV_ID_RR0_LVR_EXT_ADDR : 0),
	writel(prepare_rr0_dev_address(dev->boardinfo->base.addr),
	       master->regs + DEV_ID_RR0(data->id));
	writel(dev->boardinfo->lvr, master->regs + DEV_ID_RR2(data->id));
	writel(readl(master->regs + DEVS_CTRL) |
@@ -1518,7 +1511,6 @@ static const struct i3c_master_controller_ops cdns_i3c_master_ops = {
	.send_ccc_cmd = cdns_i3c_master_send_ccc_cmd,
	.priv_xfers = cdns_i3c_master_priv_xfers,
	.i2c_xfers = cdns_i3c_master_i2c_xfers,
	.i2c_funcs = cdns_i3c_master_i2c_funcs,
	.enable_ibi = cdns_i3c_master_enable_ibi,
	.disable_ibi = cdns_i3c_master_disable_ibi,
	.request_ibi = cdns_i3c_master_request_ibi,
Loading