From: Boris Brezillon <bbrezillon@kernel.org>
To: vitor <vitor.soares@synopsys.com>
Cc: Przemyslaw Gaj <pgaj@cadence.com>,
psroka@cadence.com, linux-i3c@lists.infradead.org,
rafalc@cadence.com
Subject: Re: [PATCH 1/2] i3c: Add support for HDR modes.
Date: Fri, 22 Feb 2019 15:52:38 +0100 [thread overview]
Message-ID: <20190222155238.3dc4ab8f@kernel.org> (raw)
In-Reply-To: <cb17ee91-bad8-03d4-cc9f-e7095cf17011@synopsys.com>
On Thu, 21 Feb 2019 15:15:57 +0000
vitor <vitor.soares@synopsys.com> wrote:
> Hi Przemek,
>
> Sorry for the late response.
>
> On 13/12/18 12:18, Przemyslaw Gaj wrote:
> > HDR (High Data Rate) modes is an important feature of the I3C protocol
> > as it allows to get higher throughput than with the SDR (Single Data
> > Rate) mode.
> >
> > Add new controller hooks and extend the I3C device API to expose this
> > new feature.
> >
> > This feature was originally created by Boris Brezillon
> > <boris.brezillon@bootlin.com>.
> >
> > Signed-off-by: Przemyslaw Gaj <pgaj@cadence.com>
> > ---
> > drivers/i3c/device.c | 37 +++++++++++++++++++++++++++++++++++++
> > drivers/i3c/internals.h | 3 +++
> > drivers/i3c/master.c | 31 +++++++++++++++++++++++++++++++
> > include/linux/i3c/device.h | 29 +++++++++++++++++++++++++++++
> > include/linux/i3c/master.h | 7 +++++++
> > 5 files changed, 107 insertions(+)
> >
> > diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
> > index 69cc040..97910aa 100644
> > --- a/drivers/i3c/device.c
> > +++ b/drivers/i3c/device.c
> > @@ -51,6 +51,43 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev,
> > EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers);
> >
> > /**
> > + * i3c_device_send_hdr_cmds() - send HDR commands to a specific device
> > + *
> > + * @dev: device to which these commands should be sent
> > + * @xfers: array of commands
> > + * @nxfers: number of commands
> > + *
> > + * Send one or several HDR commands to @dev.
> > + *
> > + * This function can sleep and thus cannot be called in atomic context.
> > + *
> > + * Return: 0 in case of success, a negative error core otherwise.
> > + */
> > +int i3c_device_send_hdr_cmds(struct i3c_device *dev,
> > + struct i3c_hdr_cmd *cmds,
> > + int ncmds)
> > +{
> > + int ret, i;
> > + enum i3c_hdr_mode mode;
> > +
> > + if (ncmds < 1)
> > + return 0;
> > +
> > + mode = cmds[0].mode;
> > + for (i = 1; i < ncmds; i++) {
> > + if (mode != cmds[i].mode)
> > + return -EINVAL;
> > + }
> > +
> > + i3c_bus_normaluse_lock(dev->bus);
> > + ret = i3c_dev_send_hdr_cmds_locked(dev->desc, cmds, ncmds);
> > + i3c_bus_normaluse_unlock(dev->bus);
> > +
> > + return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(i3c_device_send_hdr_cmds);
> > +
> > +/**
> > * i3c_device_get_info() - get I3C device information
> > *
> > * @dev: device we want information on
> > diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
> > index 86b7b44..46c4de7 100644
> > --- a/drivers/i3c/internals.h
> > +++ b/drivers/i3c/internals.h
> > @@ -18,6 +18,9 @@ void i3c_bus_normaluse_unlock(struct i3c_bus *bus);
> > int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
> > struct i3c_priv_xfer *xfers,
> > int nxfers);
> > +int i3c_dev_send_hdr_cmds_locked(struct i3c_dev_desc *dev,
> > + struct i3c_hdr_cmd *cmds,
> > + int ncmds);
> > int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev);
> > int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev);
> > int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
> > diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> > index e98b600..16d6dd5 100644
> > --- a/drivers/i3c/master.c
> > +++ b/drivers/i3c/master.c
> > @@ -2791,6 +2791,37 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
> > return master->ops->priv_xfers(dev, xfers, nxfers);
> > }
> >
> > +int i3c_dev_send_hdr_cmds_locked(struct i3c_dev_desc *dev,
> > + struct i3c_hdr_cmd *cmds,
> > + int ncmds)
> > +{
> > + struct i3c_master_controller *master;
> > + int i;
> > +
> > + if (!dev)
> > + return -ENOENT;
> > +
> > + master = i3c_dev_get_master(dev);
> > + if (!master || !cmds)
> > + return -EINVAL;
> > +
> > + if (master->op_mode == I3C_SLAVE_MODE) {
> > + if (i3c_master_request_mastership(master))
> > + return -EIO;
> > + }
>
> This patch seems to be applied on top of secondary master patch proposal.
>
> I think it is better to remove the secondary master stuffs from here.
>
> > +
> > + if (!master->ops->send_hdr_cmds)
> > + return -ENOTSUPP;
> > +
> > + for (i = 0; i < ncmds; i++) {
> > + if (!(master->this->info.hdr_cap & BIT(cmds->mode)))
> > + return -ENOTSUPP;
> > + }
> > +
> > + return master->ops->send_hdr_cmds(dev, cmds, ncmds);
> > +}
> > +
> > +
> > int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev)
> > {
> > struct i3c_master_controller *master;
> > diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
> > index 5ecb055..75a947f 100644
> > --- a/include/linux/i3c/device.h
> > +++ b/include/linux/i3c/device.h
> > @@ -49,6 +49,31 @@ enum i3c_hdr_mode {
> > I3C_HDR_TSL,
> > };
> >
> > +#define I3C_HDR_GEN_WRITE_CMD(id) (id)
> > +#define I3C_HDR_VENDOR_WRITE_CMD(id) (0x20 + (id))
> > +#define I3C_HDR_IS_READ_CMD BIT(7)
> > +#define I3C_HDR_GEN_READ_CMD(id) (0x80 + (id))
> > +#define I3C_HDR_VENDOR_READ_CMD(id) (0xa0 + (id))
> > +
> > +/**
> > + * struct i3c_hdr_cmd - I3C HDR command
> > + * @mode: HDR mode selected for this command
> > + * @code: command opcode. Bit 7 encodes the direction of the data transfer, if
> > + * set this is a read, otherwise this is a write
> > + * @ndatawords: number of data words (a word is 16bits wide) to transfer
> > + * @data: input/output buffer
> > + */
> > +struct i3c_hdr_cmd {
> > + enum i3c_hdr_mode mode;
> > + u8 code;
> > + int ndatawords;
> > + union {
> > + u16 *in;
> > + const u16 *out;
> > + } data;
> > +};
> > +
> > +
> > /**
> > * struct i3c_priv_xfer - I3C SDR private transfer
> > * @rnw: encodes the transfer direction. true for a read, false for a write
> > @@ -289,6 +314,10 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev,
> > struct i3c_priv_xfer *xfers,
> > int nxfers);
> >
> > +int i3c_device_send_hdr_cmds(struct i3c_device *dev,
> > + struct i3c_hdr_cmd *cmds,
> > + int ncmds);
> > +
> > void i3c_device_get_info(struct i3c_device *dev, struct i3c_device_info *info);
> >
> > struct i3c_ibi_payload {
> > diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
> > index ada956a..fd50473 100644
> > --- a/include/linux/i3c/master.h
> > +++ b/include/linux/i3c/master.h
> > @@ -386,6 +386,10 @@ struct i3c_bus {
> > * This method is mandatory.
> > * @priv_xfers: do one or several private I3C SDR transfers
> > * This method is mandatory.
> > + * @send_hdr_cmds: send one or several HDR commands. If there is more than one
> > + * command, they should ideally be sent in the same HDR
> > + * transaction.
> > + * This method is optional.
> > * @attach_i2c_dev: called every time an I2C device is attached to the bus.
> > * This is a good place to attach master controller specific
> > * data to I2C devices.
> > @@ -457,6 +461,9 @@ struct i3c_master_controller_ops {
> > int (*priv_xfers)(struct i3c_dev_desc *dev,
> > struct i3c_priv_xfer *xfers,
> > int nxfers);
> > + int (*send_hdr_cmds)(struct i3c_dev_desc *dev,
> > + const struct i3c_hdr_cmd *cmds,
> > + int ncmds);
> > int (*attach_i2c_dev)(struct i2c_dev_desc *dev);
> > void (*detach_i2c_dev)(struct i2c_dev_desc *dev);
> > int (*i2c_xfers)(struct i2c_dev_desc *dev,
>
> With this approach the controller between a start and stop can only transmit in SDR or HDR.
>
> This is limited for devices that need the following frame:
> <Start><SDR xfer><Repeated Start><HDR command><Stop>
If this is a use case we want to support, then we should probably have
something more generic than what we currently have.
Something like
enum i3c_xfer_type {
I3C_CCC_XFER,
I3C_SDR_XFER,
I3C_HDR_XFER,
}
struct i3c_xfer {
enum i3c_xfer_type type;
union {
struct i3c_ccc_cmd ccc;
struct i3c_priv_xfer sdr;
struct i3c_hdr_cmd hdr;
};
}
struct i3c_master_controller_ops {
...
int (*i3c_xfers)(struct i3c_dev_desc *dev,
struct i3c_xfer *xfers,
int nxfers);
...
};
_______________________________________________
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
next prev parent reply other threads:[~2019-02-22 14:52 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-13 12:18 [PATCH 0/2] Add the I3C HDR modes Przemyslaw Gaj
2018-12-13 12:18 ` [PATCH 1/2] i3c: Add support for " Przemyslaw Gaj
2018-12-13 12:44 ` Boris Brezillon
2019-02-21 15:15 ` vitor
2019-02-22 14:52 ` Boris Brezillon [this message]
2019-02-22 15:02 ` Przemyslaw Gaj
2019-02-22 17:41 ` vitor
2019-02-25 8:56 ` Boris Brezillon
2019-02-25 12:56 ` vitor
2019-02-25 13:10 ` Boris Brezillon
2019-02-25 16:45 ` vitor
2019-02-25 17:03 ` Boris Brezillon
2018-12-13 12:18 ` [PATCH 2/2] i3c: master: cdns: Add support for HDR-DDR mode Przemyslaw Gaj
2018-12-13 12:45 ` Boris Brezillon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190222155238.3dc4ab8f@kernel.org \
--to=bbrezillon@kernel.org \
--cc=linux-i3c@lists.infradead.org \
--cc=pgaj@cadence.com \
--cc=psroka@cadence.com \
--cc=rafalc@cadence.com \
--cc=vitor.soares@synopsys.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).