RE: [PATCH v10 1/2] i2c: buses: add i2c bus driver for NVIDIA GPU

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Peter

> >>>>>>>>> +		if (msgs[i].flags & I2C_M_RD) {
> >>>>>>>>> +			/* gpu_i2c_read has implicit start and stop */
> >>>>>>>>> +			status = gpu_i2c_read(i2cd, msgs[i].buf,
> >> msgs[i].len);
> >>>>>>>>> +			if (status < 0)
> >>>>>>>>> +				return status;
> >>>>>>>>> +		} else {
> >>>>>>>>> +			/* start on first write message */
> >>>>>>>>> +			if (i == 0) {
> >>>>>>>>
> >>>>>>>> This "if (i == 0)" test is completely bogus to me. I fail to
> >>>>>>>> see why the meat of the block should not happen for both writes
> >>>>>>>> in a double-write transfer.
> >>>>>>>>
> >>>>>>>> If the second message is a write, you do not issue any start
> >>>>>>>> nor do you write out the address for the second message. You
> >>>>>>>> want to generate the following for a transfer consisting of 2 write-
> messages:
> >>>>>>>>
> >>>>>>>>   S Addr Wr [A] Data [A] ... S Addr Wr [A] Data [A] ... P
> >>>>>>>>                              =============
> >>>>>>>>
> >>>>>>>> (where "..." denotes further optional "Data [A]" instances)
> >>>>>>>>
> >>>>>>>> As is, the stuff underlined by equal signs are not generated,
> >>>>>>>> at least as I read the code.
> >>>>>>>>
> >>>>>>>> This is what I meant in my comment around this area for the v9
> patch.
> >>>>>>>
> >>>>>>> Oh, I just realized, this probably means that the ccg_write
> >>>>>>> function in patch
> >>>>>>> 2/2 asks for the wrong thing. If this code actually works, the
> >>>>>>> client driver should probably ask for a single-message transfer
> >>>>>>> consisting of the 2-byte rab concatenated with the data buffer.
> >>>>>>> And that actually makes sense, there is no reason to split the
> >>>>>>> two
> >>>>>>> (dependent) parts of the write into separate messages.
> >>>>>> That would require to create new buffer and copy data for each
> >>>>>> write request from UCSI core driver for sending UCSI command.
> >>>>>> This doesn't look proper way of doing it.
> >>>>>
> >>>>> Well, that's the way master_xfer works, so you will just have to
> >>>>> live with it if you do not want a stop in the middle.
> >>>>
> >>>> Bzzt, s/stop/restart/
> >>> Obviously, a stop in middle will not work. For any read or write
> >>> request,
> >>
> >> Yes, with "s/stop/restart/", I meant "replace stop with restart", and
> >> not "stop followed by restart". That's pretty standard notation, but
> >> sorry if that was not clear.
> >>
> >>> 2 byte rab write has to go first. We anyway have to separate rab
> >>> part in read transactions so write should be okay to have separate
> >>> rab write message.
> >>
> >> That is not at all certain. The two below transfers need not mean the
> >> same thing at all.
> >>
> >> S Addr Wr [A] rab1 [A] rab2 [A] Data [A] ... P S Addr Wr [A] rab1 [A]
> >> rab2 [A] S Addr Wr [A] Data [A] ... P
> >>
> >> In fact, I strongly suspect that for the latter case, the device will
> >> interpret the first two Data bytes as rab and that you therefore have
> >> to make sure that the first transfer (w/o restart) is what you generate in
> ccg_write.
> >>
> >>> All the client driver of this needs to create messages in pairs
> >>> where first one will always be a rab write and second one either read or
> write.
> >>> I can add a check for this condition in master_xfer if needed.
> >>>
> >>> Do you still see any issue with this?
> >>
> >> Yes, this is very much an issue. master_xfer has to start each
> >> message with a start for the first message, and a restart for
> >> subsequent messages. And after the final message there should be a
> >> stop. All starts/restarts should be followed by the address and the
> >> read/write bit. Then data in the given direction. The master_xfer
> >> function should never do any device specific checks for device
> >> specific conditions. It simply should not care about which client
> >> driver is currently using it, and instead just stick to implementing the
> master_xfer api so that all client drivers know what to expect. No cludges.
> >
> > I didn't get how read will happen. Read will also require a 2 byte rab
> > write and followed by read.
> >
> > Are you saying to have two messages for reads [rab + read] and
> > combined (rab and write) single message for write?
> > Then for read: rab is written first followed by reads and then actual explicit
> stop?
> >
> > for (i = 0; i < num; i++)
> > 	if (Read) {
> > 		read (without stop);
> > 	} else  {
> > 		start;
> > 		addr;
> > 		write;
> > 	}
> > }
> > stop;
> 
> Yes, exactly like that (just missing a { for the for loop). If you can do reads
> without an implicit stop, that's excellent news!
> 
> My guess is that with the above, you can actually program the I2C_MST_ADDR
> register inside the "if (Read)" branch and then remove the I2C_AQ_COMB |
> I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR quirks.

We need I2C_MST_ADDR to be programmed even in a single write message.
If we move it inside "if (Read)" branch then a single write message will not get it.

How does the below look?

for (i = 0; i < num; i++) {
	write msg[i].addr to I2C_MST_ADDR;
 	if (Read) {
 		read (without stop);
 	} else  {
 		start;
 		addr;
 		write;
 	}
 }
 stop;

Thanks
Ajay

--
nvpublic
--
> Cheers,
> Peter
> 
> >
> > Thanks
> > Ajay
> >
> > --
> > nvpublic
> > --
> >>
> >> Cheers,
> >> Peter





[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux