Hi, On Thu, Sep 16, 2021 at 1:15 PM Stephen Boyd <swboyd@xxxxxxxxxxxx> wrote: > > > > > + return ret; > > > > + } > > > > + > > > > + /* Assume it's good */ > > > > + msg->reply = 0; > > > > + > > > > + addr_len[0] = msg->address & 0xff; > > > > + addr_len[1] = (msg->address >> 8) & 0xff; > > > > + addr_len[2] = ((msg->request << 4) & SWAUX_CMD_MASK) | > > > > + ((msg->address >> 16) & SWAUX_ADDR_19_16_MASK); > > > > > > It really feels like this out to be possible with some sort of > > > cpu_to_le32() API. We're shoving msg->address into 3 bytes and then > > > adding in the request and some length. So we could do something like: > > > > > > u32 addr_len; > > > > > > addr_len = FIELD_PREP(SWAUX_ADDR_MASK, msg->address); > > > addr_len |= FIELD_PREP(SWAUX_CMD_MASK, msg->request); > > > if (len) > > > addr_len |= FIELD_PREP(LEN_MASK, len - 1); > > > else > > > addr_len |= FIELD_PREP(LEN_MASK, SWAUX_NO_PAYLOAD ); > > > > > > cpu_to_le32s(&addr_len); > > > > > > regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, &addr_len, sizeof(addr_len)); > > > > You're arguing that your version of the code is more efficient? Easier > > to understand? Something else? To me, Philip's initial version is > > crystal clear and easy to map to the bridge datasheet but I need to > > think more to confirm that your version is right. Thinking is hard and > > I like to avoid it when possible. > > > > In any case, it's definitely bikeshedding and I'll yield if everyone > > likes the other version better. ;-) > > Yeah it's bikeshedding. I don't really care about this either but I find > it easier to read when the assignment isn't wrapped across multiple > lines. If the buffer approach is preferable then maybe use the address > macros to clarify which register is being set? > > unsigned int base = PAGE0_SWAUX_ADDR_7_0; > > addr_len[PAGE0_SWAUX_ADDR_7_0 - base] = msg->address; > addr_len[PAGE0_SWAUX_ADDR_15_8 - base] = msg->address >> 8; > addr_len[PAGE0_SWAUX_ADDR_23_16 - base] = msg->address >> 16; > addr_len[PAGE0_SWAUX_ADDR_23_16 - base] |= msg->request << 4; Sure, this looks nice to me. :-) > > > > + return ret; > > > > + } > > > > + > > > > + switch (data & SWAUX_STATUS_MASK) { > > > > + /* Ignore the DEFER cases as they are already handled in hardware */ > > > > + case SWAUX_STATUS_NACK: > > > > + case SWAUX_STATUS_I2C_NACK: > > > > + /* > > > > + * The programming guide is not clear about whether a I2C NACK > > > > + * would trigger SWAUX_STATUS_NACK or SWAUX_STATUS_I2C_NACK. So > > > > + * we handle both cases together. > > > > + */ > > > > + if (is_native_aux) > > > > + msg->reply |= DP_AUX_NATIVE_REPLY_NACK; > > > > + else > > > > + msg->reply |= DP_AUX_I2C_REPLY_NACK; > > > > + > > > > + len = data & SWAUX_M_MASK; > > > > + return len; > > > > > > Why no 'return data & SWAUX_M_MASK;' and skip the assignment? > > > > Actually, I think it's the "return" that's a bug, isn't it? If we're > > doing a "read" and we're returning a positive number of bytes then we > > need to actually _read_ them. Reading happens below, doesn't it? > > > > Oh I missed that. We're still supposed to return data to upper > layers on a NACKed read? It seems highly likely not to matter in practice, but: * The docs from parade clearly state that when a NAK is returned that the number of bytes transferred before the NAK will be provided to us. * The i2c interface specifies NAK not as a return code but as a bit in the "reply". That presumably is to let us return the number of bytes transferred before the NAK to the next level up. * If we're returning the number of bytes and it's a read then we'd better return the data too! It looks like we handled this OK in the TI bridge driver. From reading the TI docs we'll get both AUX_IRQ_STATUS_AUX_SHORT and AUX_IRQ_STATUS_NAT_I2C_FAIL in the case of a partial transfer and so we'll do the right thing. -Doug