1
0
Fork 0

* 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
alistair/sunxi64-5.4-dsi
Linus Torvalds 2019-07-09 09:04:31 -07:00
commit 96407298ff
6 changed files with 71 additions and 44 deletions

View File

@ -38,6 +38,6 @@ Example:
nunchuk: nunchuk@52 { nunchuk: nunchuk@52 {
compatible = "nintendo,nunchuk"; compatible = "nintendo,nunchuk";
reg = <0x52 0x80000010 0>; reg = <0x52 0x0 0x10>;
}; };
}; };

View File

@ -39,7 +39,9 @@ valid here, but several new properties have been added.
New constraint on existing properties: New constraint on existing properties:
-------------------------------------- --------------------------------------
- reg: contains 3 cells - 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 + second cell: shall be 0

View File

@ -91,6 +91,12 @@ void i3c_bus_normaluse_unlock(struct i3c_bus *bus)
up_read(&bus->lock); 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) static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev)
{ {
return container_of(dev, struct i3c_master_controller, 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[] = { static const char * const i3c_bus_mode_strings[] = {
[I3C_BUS_MODE_PURE] = "pure", [I3C_BUS_MODE_PURE] = "pure",
[I3C_BUS_MODE_MIXED_FAST] = "mixed-fast", [I3C_BUS_MODE_MIXED_FAST] = "mixed-fast",
[I3C_BUS_MODE_MIXED_LIMITED] = "mixed-limited",
[I3C_BUS_MODE_MIXED_SLOW] = "mixed-slow", [I3C_BUS_MODE_MIXED_SLOW] = "mixed-slow",
}; };
@ -565,20 +572,39 @@ static const struct device_type i3c_masterdev_type = {
.groups = i3c_masterdev_groups, .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; i3cbus->mode = mode;
if (!i3cbus->scl_rate.i3c) switch (i3cbus->mode) {
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE; case I3C_BUS_MODE_PURE:
if (!i3cbus->scl_rate.i3c)
if (!i3cbus->scl_rate.i2c) { i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
if (i3cbus->mode == I3C_BUS_MODE_MIXED_SLOW) break;
i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE; case I3C_BUS_MODE_MIXED_FAST:
else case I3C_BUS_MODE_MIXED_LIMITED:
i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_PLUS_SCL_RATE; 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 * I3C/I2C frequency may have been overridden, check that user-provided
* values are not exceeding max possible frequency. * values are not exceeding max possible frequency.
@ -924,9 +950,8 @@ int i3c_master_defslvs_locked(struct i3c_master_controller *master)
ndevs++; ndevs++;
defslvs = i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR, defslvs = i3c_ccc_cmd_dest_init(&dest, I3C_BROADCAST_ADDR,
sizeof(*defslvs) + struct_size(defslvs, slaves,
((ndevs - 1) * ndevs - 1));
sizeof(struct i3c_ccc_dev_desc)));
if (!defslvs) if (!defslvs)
return -ENOMEM; return -ENOMEM;
@ -1963,12 +1988,19 @@ of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
if (ret) if (ret)
return 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]. */ /* LVR is encoded in reg[2]. */
boardinfo->lvr = 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); list_add_tail(&boardinfo->node, &master->boardinfo.i2c);
of_node_get(node); of_node_get(node);
@ -2111,16 +2143,14 @@ static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap,
return ret ? ret : nxfers; 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 I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
return master->ops->i2c_funcs(master);
} }
static const struct i2c_algorithm i3c_master_i2c_algo = { static const struct i2c_algorithm i3c_master_i2c_algo = {
.master_xfer = i3c_master_i2c_adapter_xfer, .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) 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) static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops)
{ {
if (!ops || !ops->bus_init || !ops->priv_xfers || if (!ops || !ops->bus_init || !ops->priv_xfers ||
!ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers || !ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers)
!ops->i2c_funcs)
return -EINVAL; return -EINVAL;
if (ops->request_ibi && if (ops->request_ibi &&
@ -2417,6 +2446,7 @@ int i3c_master_register(struct i3c_master_controller *master,
const struct i3c_master_controller_ops *ops, const struct i3c_master_controller_ops *ops,
bool secondary) bool secondary)
{ {
unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
struct i3c_bus *i3cbus = i3c_master_get_bus(master); struct i3c_bus *i3cbus = i3c_master_get_bus(master);
enum i3c_bus_mode mode = I3C_BUS_MODE_PURE; enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;
struct i2c_dev_boardinfo *i2cbi; struct i2c_dev_boardinfo *i2cbi;
@ -2458,6 +2488,9 @@ int i3c_master_register(struct i3c_master_controller *master,
mode = I3C_BUS_MODE_MIXED_FAST; mode = I3C_BUS_MODE_MIXED_FAST;
break; break;
case I3C_LVR_I2C_INDEX(1): 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): case I3C_LVR_I2C_INDEX(2):
if (mode < I3C_BUS_MODE_MIXED_SLOW) if (mode < I3C_BUS_MODE_MIXED_SLOW)
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; ret = -EINVAL;
goto err_put_dev; 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) if (ret)
goto err_put_dev; goto err_put_dev;

View File

@ -599,6 +599,7 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m)
switch (bus->mode) { switch (bus->mode) {
case I3C_BUS_MODE_MIXED_FAST: case I3C_BUS_MODE_MIXED_FAST:
case I3C_BUS_MODE_MIXED_LIMITED:
ret = dw_i2c_clk_cfg(master); ret = dw_i2c_clk_cfg(master);
if (ret) if (ret)
return ret; return ret;
@ -1060,11 +1061,6 @@ static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
kfree(data); 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) static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id)
{ {
struct dw_i3c_master *master = 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, .attach_i2c_dev = dw_i3c_master_attach_i2c_dev,
.detach_i2c_dev = dw_i3c_master_detach_i2c_dev, .detach_i2c_dev = dw_i3c_master_detach_i2c_dev,
.i2c_xfers = dw_i3c_master_i2c_xfers, .i2c_xfers = dw_i3c_master_i2c_xfers,
.i2c_funcs = dw_i3c_master_i2c_funcs,
}; };
static int dw_i3c_probe(struct platform_device *pdev) static int dw_i3c_probe(struct platform_device *pdev)

View File

@ -864,11 +864,6 @@ static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
return ret; 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 { struct cdns_i3c_i2c_dev_data {
u16 id; u16 id;
s16 ibi; 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); master->free_rr_slots &= ~BIT(slot);
i2c_dev_set_master_data(dev, data); i2c_dev_set_master_data(dev, data);
writel(prepare_rr0_dev_address(dev->boardinfo->base.addr) | writel(prepare_rr0_dev_address(dev->boardinfo->base.addr),
(dev->boardinfo->base.flags & I2C_CLIENT_TEN ?
DEV_ID_RR0_LVR_EXT_ADDR : 0),
master->regs + DEV_ID_RR0(data->id)); master->regs + DEV_ID_RR0(data->id));
writel(dev->boardinfo->lvr, master->regs + DEV_ID_RR2(data->id)); writel(dev->boardinfo->lvr, master->regs + DEV_ID_RR2(data->id));
writel(readl(master->regs + DEVS_CTRL) | 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, .send_ccc_cmd = cdns_i3c_master_send_ccc_cmd,
.priv_xfers = cdns_i3c_master_priv_xfers, .priv_xfers = cdns_i3c_master_priv_xfers,
.i2c_xfers = cdns_i3c_master_i2c_xfers, .i2c_xfers = cdns_i3c_master_i2c_xfers,
.i2c_funcs = cdns_i3c_master_i2c_funcs,
.enable_ibi = cdns_i3c_master_enable_ibi, .enable_ibi = cdns_i3c_master_enable_ibi,
.disable_ibi = cdns_i3c_master_disable_ibi, .disable_ibi = cdns_i3c_master_disable_ibi,
.request_ibi = cdns_i3c_master_request_ibi, .request_ibi = cdns_i3c_master_request_ibi,

View File

@ -48,7 +48,7 @@ struct i3c_i2c_dev_desc {
#define I3C_LVR_I2C_INDEX(x) ((x) << 5) #define I3C_LVR_I2C_INDEX(x) ((x) << 5)
#define I3C_LVR_I2C_FM_MODE BIT(4) #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 * 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 * the bus. The only impact in this mode is that the
* high SCL pulse has to stay below 50ns to trick I2C * high SCL pulse has to stay below 50ns to trick I2C
* devices when transmitting I3C frames * 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 * @I3C_BUS_MODE_MIXED_SLOW: I2C devices without 50ns spike filter are present
* on the bus * on the bus
*/ */
enum i3c_bus_mode { enum i3c_bus_mode {
I3C_BUS_MODE_PURE, I3C_BUS_MODE_PURE,
I3C_BUS_MODE_MIXED_FAST, I3C_BUS_MODE_MIXED_FAST,
I3C_BUS_MODE_MIXED_LIMITED,
I3C_BUS_MODE_MIXED_SLOW, I3C_BUS_MODE_MIXED_SLOW,
}; };
@ -390,8 +395,6 @@ struct i3c_bus {
* and i2c_put_dma_safe_msg_buf() helpers provided by the I2C * and i2c_put_dma_safe_msg_buf() helpers provided by the I2C
* framework. * framework.
* This method is mandatory. * 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 * @request_ibi: attach an IBI handler to an I3C device. This implies defining
* an IBI handler and the constraints of the IBI (maximum payload * an IBI handler and the constraints of the IBI (maximum payload
* length and number of pre-allocated slots). * 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); void (*detach_i2c_dev)(struct i2c_dev_desc *dev);
int (*i2c_xfers)(struct i2c_dev_desc *dev, int (*i2c_xfers)(struct i2c_dev_desc *dev,
const struct i2c_msg *xfers, int nxfers); const struct i2c_msg *xfers, int nxfers);
u32 (*i2c_funcs)(struct i3c_master_controller *master);
int (*request_ibi)(struct i3c_dev_desc *dev, int (*request_ibi)(struct i3c_dev_desc *dev,
const struct i3c_ibi_setup *req); const struct i3c_ibi_setup *req);
void (*free_ibi)(struct i3c_dev_desc *dev); void (*free_ibi)(struct i3c_dev_desc *dev);