Post by Rajesh KumarHi,
Re-posting the questions, just in case if its missed in other conversation.
By "i2c clock frequency", I mean the internal base frequency only, which
drives the chip. I thought data will be transferred on bus based on the
base frequency. So, thought both bus and base frequency are same. But from
what you said, seems both are different. So, based on the setting in
*_HCNT/LCNT register, the bus frequency (which is the rate at which data is
transferred) will change for a particular base frequency. Is that right?
So, few questions here
1) As you said, we need to have a base frequency of 150 Mhz in our case.
So, do we need to program that IG4_REG_CLK_PARMS to 150 Mhz (0x8F0D180)?
And can this be done at the same time when programming the HCNT/LNCT
registers?
I don't have this hardware, and I don't have a datasheet that describes
the IG4_REG_CLK_PARMS register mentioned in the driver, so I don't
really have an answer. I suspect the hardware should set that register
with information that lets the driver know what the base clock speed
is. Using that information, the driver could calculate the proper
values for HCNT/LCNT.
Right now the driver lacks *any* support for changing bus speeds. That
will be easy to fix, once we figure out:
1. What is in the IG4_REG_CLK_PARMS register?
2. What do we do about versions of the hardware that don't support
that register?
Post by Rajesh Kumar2) Not sure how that 111Hz value is arrived. Can you please explain this
calculation. So, that I can derive the appropriate values for HCNT/LCNT for
different speeds at 150Mhz base clock.
It's based on the comment (which I feel certain must be wrong) that the
base clock is 25,000 Hz. With HCNT,LCNT set to 100,125, one cycle of
the SCL line will last 225 base clock cycles. 1/25000 = 0.000040, that
times 225 is 0.009 seconds per SCL cycle. 1/.009 = 111.111 Hz.
FWIW, an i2c bus will run fine at 111Hz, it'll just take forever to get
anything done. But I don't think the bus is really running at 111Hz,
because I don't think the base clock is really 25KHz, I think the
comment block is just wrong about all of that.
Post by Rajesh Kumar3) "Default HCNT/LCNT register values would be consistent with an internal
base clock speed of 1GHz", Does it mean with those values, all speeds can
be achieved until 1GHz clock?
Well, the defaults I mentioned are from the datasheet cited in the
driver code. Those defaults made me think the base clock was 1GHz on
that particular hardware. I just realized that I was off by an order of
magnitude, I think I was mixing numbers from the driver and numbers
from the datasheet in my head. The default HCNT,LCNT in that datasheet
are 612+706=1318 base cycles to give an SCL rate of 100KHz. So
1318*100000 is 131.8MHz, a very reasonable number.
In your world you want the 150MHz base clock to generate the 100Hz SCL,
so 150000000/100000 = 1500. My inclination would be to split that in
half and have HCNT,LCNT be 750,750, but for some reason there seems to
be a bias on this hardware for having HCNT be slightly longer than
LCNT, so maybe 775,725. Maybe that's an attempt to compensate for the
fact that high levels on the clock line are accomplished with a pullup
resistor, and it takes slightly longer for the line to "drift up" to a
high state via the pullup, compared to being driven low which would
happen quickly.
I would expect the default values of the HCNT/LCNT registers would be
right for any given hardware... whoever configures the IP block in a
SoC would configure the base clock value and the default HCNT/LCNT
values to match each other. Putting it that way makes me think that
maybe the right thing to do in the driver is just stop setting
HCNT/LCNT at all, and rely on the hardware to be configured correctly
by default. It's worth a try.
It would also be interesting to just print out those values. In the
driver on lines 571-575 the code reads all those registers and does
nothing with them. If you look in the dragonflybsd version of the
driver it printed out all those values after reading them; whoever
imported the driver to freebsd just deleted all the kprintf() lines and
left the register reads.
-- Ian