Commit 96407298 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'i3c/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux

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
......@@ -38,6 +38,6 @@ Example:
nunchuk: nunchuk@52 {
compatible = "nintendo,nunchuk";
reg = <0x52 0x80000010 0>;
reg = <0x52 0x0 0x10>;
};
};
......@@ -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
......
......@@ -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)
{
i3cbus->mode = mode;
struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);
if (!i3cbus->scl_rate.i3c)
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
i3cbus->mode = mode;
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;
switch (i3cbus->mode) {
case I3C_BUS_MODE_PURE:
if (!i3cbus->scl_rate.i3c)
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_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;
......
......@@ -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)
......
......@@ -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,
......
......@@ -48,7 +48,7 @@ struct i3c_i2c_dev_desc {
#define I3C_LVR_I2C_INDEX(x) ((x) << 5)
#define I3C_LVR_I2C_FM_MODE BIT(4)
#define I2C_MAX_ADDR GENMASK(9, 0)
#define I2C_MAX_ADDR GENMASK(6, 0)
/**
* struct i2c_dev_boardinfo - I2C device board information
......@@ -250,12 +250,17 @@ struct i3c_device {
* the bus. The only impact in this mode is that the
* high SCL pulse has to stay below 50ns to trick I2C
* devices when transmitting I3C frames
* @I3C_BUS_MODE_MIXED_LIMITED: I2C devices without 50ns spike filter are
* present on the bus. However they allow
* compliance up to the maximum SDR SCL clock
* frequency.
* @I3C_BUS_MODE_MIXED_SLOW: I2C devices without 50ns spike filter are present
* on the bus
*/
enum i3c_bus_mode {
I3C_BUS_MODE_PURE,
I3C_BUS_MODE_MIXED_FAST,
I3C_BUS_MODE_MIXED_LIMITED,
I3C_BUS_MODE_MIXED_SLOW,
};
......@@ -390,8 +395,6 @@ struct i3c_bus {
* and i2c_put_dma_safe_msg_buf() helpers provided by the I2C
* framework.
* This method is mandatory.
* @i2c_funcs: expose the supported I2C functionalities.
* This method is mandatory.
* @request_ibi: attach an IBI handler to an I3C device. This implies defining
* an IBI handler and the constraints of the IBI (maximum payload
* length and number of pre-allocated slots).
......@@ -437,7 +440,6 @@ struct i3c_master_controller_ops {
void (*detach_i2c_dev)(struct i2c_dev_desc *dev);
int (*i2c_xfers)(struct i2c_dev_desc *dev,
const struct i2c_msg *xfers, int nxfers);
u32 (*i2c_funcs)(struct i3c_master_controller *master);
int (*request_ibi)(struct i3c_dev_desc *dev,
const struct i3c_ibi_setup *req);
void (*free_ibi)(struct i3c_dev_desc *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment