forked from Minki/linux
* 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEKmCqpbOU668PNA69Ze02AX4ItwAFAl0gTH0ACgkQZe02AX4I twCTwRAAhuaDKLP5fI16392s0G+66V82u9Kdn1pF8bD6r8wcyRjkBsp2p73VPu4D ASIKH+XDDegy8H9+N7kZ7w4dYPqei/Rb4VhsUuaaC608iDvN8DCYG2ciMOr5eggv ejFt56MeMiON9BYUbk9KQJvNfaiN4d4dtFGuRETpYEGR9NG9V8Y3oQhWOG+EcWO3 RBKYNi6QDo1y5NEhrsr8m7fdz0S1F8A7DgPirwkARYAAl9LBmdUllt8+h+WHUt7I 1GJwA4ZCgXJYSGXw6Vf2p8RYakzAz6G7fTqx9maMRCwMqYKvucb0Opxe7jRnhS3s JPBVqwMdk3Dn4EWpWENgbGHIdJVwqOGxueKf1vtP64+WaUxG7AioS1QFcgPgSqPg 7yRbGreO0nCPmW1v2X+2DEYE4iTyB5Sf2xcRrNYyLjAyO2elVjNuzx+IMA2d3nK3 BS0kMaKjanSP1INCUsIiE/ISRQxQypTrYcoD4jpo/wV43MnOLDn93M9KrlhY5dOn M4rQg3FXiLeBhj+1NQPs6ac7LKkUgIIVl8+z2C8z+4DoY1LT+DsxI31YGqRly/H3 quRtBIpCXVDxd69V9bPWpINZhXeP9ccgHDBTwfQJQk8bNfdJk4dh5ydntnO9rqmp nXhBPKgww0BlHecihrIf+RpxH4q6XmvFdpCDNTH1pgdtLCwblcQ= =Uj8o -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
96407298ff
@ -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)
|
||||
{
|
||||
struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);
|
||||
|
||||
i3cbus->mode = mode;
|
||||
|
||||
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;
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user