[U-Boot] [PATCH v2] mxs: i2c: Implement algorithm to set up arbitrary i2c speed
Marek Vasut
marex at denx.de
Sat Dec 1 05:10:47 CET 2012
Dear Heiko Schocher,
> Hello Marek,
[...]
> > diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
> > index 006fb91..b040535 100644
> > --- a/drivers/i2c/mxs_i2c.c
> > +++ b/drivers/i2c/mxs_i2c.c
> > @@ -28,6 +28,7 @@
> >
> > #include<common.h>
> > #include<malloc.h>
> >
> > +#include<i2c.h>
> >
> > #include<asm/errno.h>
> > #include<asm/io.h>
> > #include<asm/arch/clock.h>
> >
> > @@ -40,6 +41,7 @@ void mxs_i2c_reset(void)
> >
> > {
> >
> > struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
> > int ret;
> >
> > + int speed = i2c_get_bus_speed();
> >
> > ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
> > if (ret) {
> >
> > @@ -53,6 +55,8 @@ void mxs_i2c_reset(void)
> >
> > &i2c_regs->hw_i2c_ctrl1_clr);
> >
> > writel(I2C_QUEUECTRL_PIO_QUEUE_MODE,&i2c_regs->hw_i2c_queuectrl_set);
> >
> > +
> > + i2c_set_bus_speed(speed);
> >
> > }
>
> This change is not described in the patch description, please fix.
I suspect I'll move this to a separate patch.
> > void mxs_i2c_setup_read(uint8_t chip, int len)
> >
> > @@ -210,62 +214,29 @@ int i2c_probe(uchar chip)
> >
> > return ret;
> >
> > }
> >
> > -static struct mxs_i2c_speed_table {
>
> [...]
>
> > int i2c_set_bus_speed(unsigned int speed)
> > {
> >
> > struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
> >
> > - struct mxs_i2c_speed_table *spd = mxs_i2c_speed_to_cfg(speed);
> >
> > - if (!spd) {
> > - printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
> > + uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
> > + uint32_t base = ((clk / speed) - 38) / 2;
> > + uint16_t high_count = base + 3;
> > + uint16_t low_count = base - 3;
> > + uint16_t rcv_count = (high_count * 3) / 4;
> > + uint16_t xmit_count = low_count / 4;
>
> a lot of magic constants ...
True ... and they have no other meaning than to align stuff on the scope ;-)
> > +
> > + if (speed> 540000) {
> > + printf("MXS I2C: Speed too high (%d Hz)\n", speed);
> > + return -EINVAL;
> > + }
> > +
> > + if (speed< 12000) {
> > + printf("MXS I2C: Speed too low (%d Hz)\n", speed);
> >
> > return -EINVAL;
> >
> > }
> >
> > - writel(spd->timing0,&i2c_regs->hw_i2c_timing0);
> > - writel(spd->timing1,&i2c_regs->hw_i2c_timing1);
> > + writel((high_count<< 16) | rcv_count,&i2c_regs->hw_i2c_timing0);
> > + writel((low_count<< 16) | xmit_count,&i2c_regs->hw_i2c_timing1);
>
> ^ ^
> spaces
Could this be your mailer's issue?
[...]
> ... and here a lot of magic constants too ... as this is a result of
> measuring ... we should at least note here, that we have this values
> from a scope session and the values in the manual seem to be not
> correct ...
True.
> Hmm... I am a little confused ... you write the
> i2c_regs->hw_i2c_timing{0,1,2} registers in i2c_set_bus_speed() but you
> return in i2c_get_bus_speed() just results from reading the
> i2c_regs->hw_i2c_timing0 register only and do some funny calculations ...
> is this correct?
Yes, the speed is configured upon boot anyway, so the timing0 register contains
result of previous call to i2c_set_bus_speed(). And if it doesn't, we can't
properly determine the speed anyway :(
> > }
> >
> > void i2c_init(int speed, int slaveadd)
>
> Thanks!
>
> bye,
> Heiko
More information about the U-Boot
mailing list