[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Zw/lH9pCrkFoXsbH@lizhi-Precision-Tower-5810>
Date: Wed, 16 Oct 2024 12:09:03 -0400
From: Frank Li <Frank.li@....com>
To: Alexandre Belloni <alexandre.belloni@...tlin.com>
Cc: linux-i3c@...ts.infradead.org, linux-kernel@...r.kernel.org,
arnd@...db.de, bbrezillon@...nel.org, boris.brezillon@...labora.com,
conor.culhane@...vaco.com, gregkh@...uxfoundation.org,
imx@...ts.linux.dev, miquel.raynal@...tlin.com,
pthombar@...ence.com, ravindra.yashvant.shinde@....com
Subject: Re: [PATCH v7 2/3] i3c: master: Extend address status bit to 4 and
add I3C_ADDR_SLOT_EXT_DESIRED
On Tue, Oct 08, 2024 at 11:18:25AM -0400, Frank Li wrote:
> Extend the address status bit to 4 and introduce the
> I3C_ADDR_SLOT_EXT_DESIRED macro to indicate that a device prefers a
> specific address. This is generally set by the 'assigned-address' in the
> device tree source (dts) file.
>
> ┌────┬─────────────┬───┬─────────┬───┐
> │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA │ T ├────┐
> └────┴─────────────┴───┴─────────┴───┘ │
> ┌─────────────────────────────────────────┘
> │ ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────┐
> └─►│Sr│7'h7E RnW=1 │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│
> └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘
>
> Some master controllers (such as HCI) need to prepare the entire above
> transaction before sending it out to the I3C bus. This means that a 7-bit
> dynamic address needs to be allocated before knowing the target device's
> UID information.
>
> However, some I3C targets may request specific addresses (called as
> "init_dyn_addr"), which is typically specified by the DT-'s
> assigned-address property. Lower addresses having higher IBI priority. If
> it is available, i3c_bus_get_free_addr() preferably return a free address
> that is not in the list of desired addresses (called as "init_dyn_addr").
> This allows the device with the "init_dyn_addr" to switch to its
> "init_dyn_addr" when it hot-joins the I3C bus. Otherwise, if the
> "init_dyn_addr" is already in use by another I3C device, the target device
> will not be able to switch to its desired address.
>
> If the previous step fails, fallback returning one of the remaining
> unassigned address, regardless of its state in the desired list.
>
> Signed-off-by: Frank Li <Frank.Li@....com>
> ---
Miquel:
Do you have a chance to check this patch again?
Frank
> Change from v6 to v7
> - always use i3c_bus_get_addr_slot_status_mask() in i3c_bus_get_free_addr
> - ((unsigned long)status & mask) in i3c_bus_set_addr_slot_status_mask()
> incase status bigger than mask;
>
> Change from v5 to v6
> - fix version number, should start v5
> - change to I3C_ADDR_SLOT_EXT_DESIRED
> - remove _ext function and direct use _mask function
> - rework commit message and comments according to Miquèl's feedback.
> - change mask type to u32
> change from v3 to v4
> - rewrite commit message and comment for i3c_bus_get_free_addr()
> ---
> drivers/i3c/master.c | 65 ++++++++++++++++++++++++++++++++++++++--------
> include/linux/i3c/master.h | 7 +++--
> 2 files changed, 59 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index dcf8d23c5941a..e0962a17de7f0 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -345,7 +345,7 @@ const struct bus_type i3c_bus_type = {
> EXPORT_SYMBOL_GPL(i3c_bus_type);
>
> static enum i3c_addr_slot_status
> -i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
> +i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
> {
> unsigned long status;
> int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
> @@ -356,11 +356,17 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
> status = bus->addrslots[bitpos / BITS_PER_LONG];
> status >>= bitpos % BITS_PER_LONG;
>
> - return status & I3C_ADDR_SLOT_STATUS_MASK;
> + return status & mask;
> }
>
> -static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
> - enum i3c_addr_slot_status status)
> +static enum i3c_addr_slot_status
> +i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
> +{
> + return i3c_bus_get_addr_slot_status_mask(bus, addr, I3C_ADDR_SLOT_STATUS_MASK);
> +}
> +
> +static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,
> + enum i3c_addr_slot_status status, u32 mask)
> {
> int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
> unsigned long *ptr;
> @@ -369,9 +375,14 @@ static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
> return;
>
> ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
> - *ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
> - (bitpos % BITS_PER_LONG));
> - *ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
> + *ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));
> + *ptr |= ((unsigned long)status & mask) << (bitpos % BITS_PER_LONG);
> +}
> +
> +static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
> + enum i3c_addr_slot_status status)
> +{
> + i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);
> }
>
> static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
> @@ -383,13 +394,44 @@ static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
> return status == I3C_ADDR_SLOT_FREE;
> }
>
> +/*
> + * ┌────┬─────────────┬───┬─────────┬───┐
> + * │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA │ T ├────┐
> + * └────┴─────────────┴───┴─────────┴───┘ │
> + * ┌─────────────────────────────────────────┘
> + * │ ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────┐
> + * └─►│Sr│7'h7E RnW=1 │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│
> + * └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘
> + * Some master controllers (such as HCI) need to prepare the entire above transaction before
> + * sending it out to the I3C bus. This means that a 7-bit dynamic address needs to be allocated
> + * before knowing the target device's UID information.
> + *
> + * However, some I3C targets may request specific addresses (called as "init_dyn_addr"), which is
> + * typically specified by the DT-'s assigned-address property. Lower addresses having higher IBI
> + * priority. If it is available, i3c_bus_get_free_addr() preferably return a free address that is
> + * not in the list of desired addresses (called as "init_dyn_addr"). This allows the device with
> + * the "init_dyn_addr" to switch to its "init_dyn_addr" when it hot-joins the I3C bus. Otherwise,
> + * if the "init_dyn_addr" is already in use by another I3C device, the target device will not be
> + * able to switch to its desired address.
> + *
> + * If the previous step fails, fallback returning one of the remaining unassigned address,
> + * regardless of its state in the desired list.
> + */
> static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
> {
> enum i3c_addr_slot_status status;
> u8 addr;
>
> for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
> - status = i3c_bus_get_addr_slot_status(bus, addr);
> + status = i3c_bus_get_addr_slot_status_mask(bus, addr,
> + I3C_ADDR_SLOT_EXT_STATUS_MASK);
> + if (status == I3C_ADDR_SLOT_FREE)
> + return addr;
> + }
> +
> + for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
> + status = i3c_bus_get_addr_slot_status_mask(bus, addr,
> + I3C_ADDR_SLOT_STATUS_MASK);
> if (status == I3C_ADDR_SLOT_FREE)
> return addr;
> }
> @@ -1918,9 +1960,10 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
> goto err_rstdaa;
> }
>
> - i3c_bus_set_addr_slot_status(&master->bus,
> - i3cboardinfo->init_dyn_addr,
> - I3C_ADDR_SLOT_I3C_DEV);
> + i3c_bus_set_addr_slot_status_mask(&master->bus,
> + i3cboardinfo->init_dyn_addr,
> + I3C_ADDR_SLOT_I3C_DEV | I3C_ADDR_SLOT_EXT_DESIRED,
> + I3C_ADDR_SLOT_EXT_STATUS_MASK);
>
> /*
> * Only try to create/attach devices that have a static
> diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
> index 2100547b2d8d2..6e5328c6c6afd 100644
> --- a/include/linux/i3c/master.h
> +++ b/include/linux/i3c/master.h
> @@ -298,7 +298,8 @@ enum i3c_open_drain_speed {
> * @I3C_ADDR_SLOT_I2C_DEV: address is assigned to an I2C device
> * @I3C_ADDR_SLOT_I3C_DEV: address is assigned to an I3C device
> * @I3C_ADDR_SLOT_STATUS_MASK: address slot mask
> - *
> + * @I3C_ADDR_SLOT_EXT_DESIRED: the bitmask represents addresses that are preferred by some devices,
> + * such as the "assigned-address" property in a device tree source.
> * On an I3C bus, addresses are assigned dynamically, and we need to know which
> * addresses are free to use and which ones are already assigned.
> *
> @@ -311,9 +312,11 @@ enum i3c_addr_slot_status {
> I3C_ADDR_SLOT_I2C_DEV,
> I3C_ADDR_SLOT_I3C_DEV,
> I3C_ADDR_SLOT_STATUS_MASK = 3,
> + I3C_ADDR_SLOT_EXT_STATUS_MASK = 7,
> + I3C_ADDR_SLOT_EXT_DESIRED = BIT(2),
> };
>
> -#define I3C_ADDR_SLOT_STATUS_BITS 2
> +#define I3C_ADDR_SLOT_STATUS_BITS 4
>
> /**
> * struct i3c_bus - I3C bus object
>
> --
> 2.34.1
>
Powered by blists - more mailing lists