Skip to contentSkip to conversation

PPC4XX Custom Board - Failing to read I2C

U-Boot txcotrader 5 participants 20 messages Apr 2, 2013 – Jul 25, 2013

lore
Share & tools
lore

txcotrader

author
#0 lore raw

Hello,

I'm looking for some direction. I'm trying to update my version of u-boot for a custom board based off of the PPC460SX. I'm struggling to understand why I cannot get past reading the I2C on the DIMM. I'm receiving this error:

CPU: AMCC PowerPC 460SX Rev. A at 231.291 MHz (PLB=33 OPB=16 EBC=4)
Security support
Bootstrap Option A - Boot ROM Location EBC (8 bits) Internal PCI arbiter enabled
32 kB I-Cache 32 kB D-Cache
Board: x Processor Board - AMCC 460SX

*** DEBUG: NDFC register configurations ***
SDR0_EBC = 0x30011ffe
SDR0_NFC0 = 0x411b0683
SDR0_PFC1 = 0x41120000
EBC0_B0CR = 0xff08a000
EBC0_B0AP = 0x10055e00
EBC0_B1CR = 0xd1018000
EBC0_B1AP = 0x018003c0
EBC0_B2CR = 0xd0018000
EBC0_B2AP = 0x03804240
EBC0_B3CR = 0x00000000
EBC0_B3AP = 0x00000000

SDR0_SDSTP0 = 0xb40b3149
SDR0_SDSTP1 = 0xe8000210
SDR0_SDSTP2 = 0x00002030
SDR0_SDSTP3 = 0xc3001380

CPR0_PLL0C = 0x40000340
CPR0_PLL1C = 0x40000340
CPR0_PLL0D = 0xb3010600
CPR0_PLL1D = 0x00010600

CPR0_PLBD  = 0x04000000
CPR0_OPBD  = 0x02000000
CPR0_PERD  = 0x01000000
CPR0_ICFG  = 0x00000000
CPR0_DDRD  = 0x02000000
L2:    512KB
EBC_BXAP_FPGA: 03804240
EBC_BXCR_FPGA_CS2: d0018000
I2C:   ready

DRAM:
spd_read(0x50) returned 0
spd_read(0x50) returned 0
DIMM slot 0: Not populated
ERROR - No memory installed. Install a DDR-SDRAM DIMM.

I2C configs:

#define CONFIG_I2C_MULTI_BUS 1
#define CONFIG_SYS_I2C_SPEED 400000 /* I2C speed
*/

/*#define CONFIG_SYS_I2C_MULTI_EEPROMS*/

#define CONFIG_SYS_I2C_EEPROM_ADDR              (0xa8>>1)
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN          1
#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS       5
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS   10

/* I2C bootstrap EEPROM */

#define IIC0_BOOTPROM_ADDR                      0x54
#define IIC0_PLX_FPGA_ADDR                      0x69
#define IIC0_PLX_PPC_ADDR                       0x6A

/* I2C bootstrap EEPROM */

#define CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR       0x52
#define CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET     0
#define CONFIG_4xx_CONFIG_BLOCKSIZE             16

/* RTC configuration */
#define CONFIG_RTC_DS1337 1
#define CONFIG_SYS_I2C_RTC_ADDR 0x68

I found myself digging pretty deep into i2c_transfer.c but I think there is a configuration error. Any advice would be greatly appreciated.

Thank you

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298.html
Sent from the U-Boot mailing list archive at Nabble.com.

#1 lore raw
Quoted 45 lines · txcotrader

Hello,

I'm looking for some direction. I'm trying to update my version of u-boot for a custom board based off of the PPC460SX. I'm struggling to understand why I cannot get past reading the I2C on the DIMM. I'm receiving this error:

CPU: AMCC PowerPC 460SX Rev. A at 231.291 MHz (PLB=33 OPB=16 EBC=4)
Security support
Bootstrap Option A - Boot ROM Location EBC (8 bits) Internal PCI arbiter enabled
32 kB I-Cache 32 kB D-Cache
Board: x Processor Board - AMCC 460SX

*** DEBUG: NDFC register configurations ***
SDR0_EBC = 0x30011ffe
SDR0_NFC0 = 0x411b0683
SDR0_PFC1 = 0x41120000
EBC0_B0CR = 0xff08a000
EBC0_B0AP = 0x10055e00
EBC0_B1CR = 0xd1018000
EBC0_B1AP = 0x018003c0
EBC0_B2CR = 0xd0018000
EBC0_B2AP = 0x03804240
EBC0_B3CR = 0x00000000
EBC0_B3AP = 0x00000000

SDR0_SDSTP0 = 0xb40b3149
SDR0_SDSTP1 = 0xe8000210
SDR0_SDSTP2 = 0x00002030
SDR0_SDSTP3 = 0xc3001380

CPR0_PLL0C = 0x40000340
CPR0_PLL1C = 0x40000340
CPR0_PLL0D = 0xb3010600
CPR0_PLL1D = 0x00010600

CPR0_PLBD  = 0x04000000
CPR0_OPBD  = 0x02000000
CPR0_PERD  = 0x01000000
CPR0_ICFG  = 0x00000000
CPR0_DDRD  = 0x02000000
L2:    512KB
EBC_BXAP_FPGA: 03804240
EBC_BXCR_FPGA_CS2: d0018000
I2C:   ready
Quoted 5 lines

DRAM:
spd_read(0x50) returned 0
spd_read(0x50) returned 0
DIMM slot 0: Not populated
ERROR - No memory installed. Install a DDR-SDRAM DIMM.

Okay, here you seem to have configured 0x50 as I2C address for the SPD EEPROM.

Quoted 22 lines

I2C configs:

#define CONFIG_I2C_MULTI_BUS 1
#define CONFIG_SYS_I2C_SPEED 400000 /* I2C speed
*/

/*#define CONFIG_SYS_I2C_MULTI_EEPROMS*/

#define CONFIG_SYS_I2C_EEPROM_ADDR              (0xa8>>1)
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN          1
#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS       5
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS   10

/* I2C bootstrap EEPROM */

#define IIC0_BOOTPROM_ADDR                      0x54
#define IIC0_PLX_FPGA_ADDR                      0x69
#define IIC0_PLX_PPC_ADDR                       0x6A

/* I2C bootstrap EEPROM */

#define CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR       0x52
#define CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET     0
#define CONFIG_4xx_CONFIG_BLOCKSIZE             16
Quoted 7 lines

/* RTC configuration */
#define CONFIG_RTC_DS1337 1
#define CONFIG_SYS_I2C_RTC_ADDR 0x68

I found myself digging pretty deep into i2c_transfer.c but I think there is a configuration error. Any advice would be greatly appreciated.

The SPD I2C EEPROM address is missing in your configs here. I assume you have something like this in your header:

#define CONFIG_SPD_EEPROM*/
#define SPD_EEPROM_ADDRESS { 0x50 }

Now change this 0x50 to the correct address. Most of the time something between 0x50 and 0x54.

Hope this helps,
Stefan

author
#2 lore raw

Thanks Stefan, great suggestion, I failed to copy those configurations into my original message.

/*-----------------------------------------------------------------------
* DDR SDRAM *----------------------------------------------------------------------*/
#if !defined(CONFIG_NAND_U_BOOT)
#define CONFIG_SPD_EEPROM 1 /* Use SPD
EEPROM for setup */
#define CONFIG_DDR_ECC 1 /* with ECC
support */

/* SPD i2c spd addresses */

 #define SPD_EEPROM_ADDRESS                      {IIC0_DIMM0_ADDR}
 #define IIC0_DIMM0_ADDR                         0x50
 #define IIC0_DIMM1_ADDR                         0x52

I am questioning my bus configurations... I haven't hooked up the scope yet, but I don't think data is hitting the bus. I don't see any areas to configure the I2C bus besides the board configuration file. Any suggestions?

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p151427.html
Sent from the U-Boot mailing list archive at Nabble.com.

#3 lore raw
Quoted 12 lines · txcotrader

Thanks Stefan, great suggestion, I failed to copy those configurations into my original message.

/*-----------------------------------------------------------------------
* DDR SDRAM *----------------------------------------------------------------------*/
#if !defined(CONFIG_NAND_U_BOOT)
#define CONFIG_SPD_EEPROM 1 /* Use SPD
EEPROM for setup */
#define CONFIG_DDR_ECC 1 /* with ECC
support */

Quoted 8 lines

/* SPD i2c spd addresses */

 #define SPD_EEPROM_ADDRESS                      {IIC0_DIMM0_ADDR}
 #define IIC0_DIMM0_ADDR                         0x50
 #define IIC0_DIMM1_ADDR                         0x52

I am questioning my bus configurations... I haven't hooked up the scope yet, but I don't think data is hitting the bus. I don't see any areas to configure the I2C bus besides the board configuration file. Any suggestions?

Are you sure that 0x50 is correct? I suggest you try this instead:

#define SPD_EEPROM_ADDRESS { IIC0_DIMM0_ADDR, IIC0_DIMM1_ADDR }

Thanks,
Stefan

#5 lore raw

Hi,

Quoted 3 lines · On Wed, 3 Apr 2013 10:29:00 -0700 (PDT) txcotrader <[email protected]> wrote:

After hooking the DIMM's I2C up to the o-scope, I don't see a clock signal. The board will boot with a u-boot version from 2007. Have you ever come across a missing I2C clock?

How many I2C busses are actually used on your board ? On which bus is the SPD EEPROM ? If it is on a I2C bus other than 0, then you have to use

#define CONFIG_SYS_SPD_BUS_NUM <your-spd-bus-num>

in the board config file.

HTH,

Anatolij

author
#7 lore raw

I feel like something "different" is happening when executing the io.h->out_8 function. Could somebody help me understand this op code

v2013.01.01 Code:
extern inline void out_8(volatile unsigned char __iomem *addr, u8 val)

{
    __asm__ __volatile__("sync;\n"
                 "stb%U0%X0 %1,%0;\n"
                 : "=m" (*addr)
                 : "r" (val));
}

Old 1.7.02 Code:
extern inline void out_8(volatile unsigned char __iomem *addr, int val)

{
    __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r"

(val));
}

So I understand the sync op code but what is going on here? Could someone with some expertise explain "stb%U0%X0 %1,%0" and "stb%U0%X0 %1,%0; eieio".

Thanks!

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p151561.html
Sent from the U-Boot mailing list archive at Nabble.com.

#8 lore raw
In reply to txcotrader

txcotrader <txcotrader <at> gmail.com> writes:

Dear txcotrader

Quoted 8 lines

By board is based off of the ppc460sx.
I only have one I2C bus.

2007 version has clock signal at 0x50 (DIMM0 I2C)
2013 version has no clock signal at 0x50

My boardconfig.h file has the same values configured.

If you haven't tried it yet ...

One suggestion, try to manually set (with 'mw' or 'mm') the registers of the your I2C controller then check the clock signal. Changes in u-boot might have inadvertently caused a different I2C base address to be used.

All the best,
Rommel

author
#10 lore raw
In reply to txcotrader

After looking deeper I've found a difference in register values when performing drivers/i2c/ppc4xx_i2c.c->i2c_transfer function.

v1.7.02 code yields:

/* Transfer is in progress

         * we have to wait for upto 5 bytes of data
         * 1 byte chip address+r/w bit then bc bytes
         * of data.
         * udelay(10) is 1 bit time at 100khz
         * Doubled for slop. 20 is too small.
         */
        i = 2*5*8;
        do {
            /* Get status */
            status = in_8((u8 *)IIC_STS);
            printf("gd_ do status->i = %d, status = %d\n", i, status);
            udelay(20);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i >

0));

gd_ do status->i = 80, status = 40

v2013.01.01 Yields:

        i = 2 * 5 * 8;
        do {
            /* Get status */
            status = in_8(&i2c->sts);
            printf("gd_ do status->i = %d, status = %d\n", i, status);
            udelay(10);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) &&
             (i > 0));

gd_ do status->i = 80, status = 40

v1.7.02 - include/4xx_i2c.h:#define IIC_STS (I2C_REGISTERS_BASE_ADDRESS+IICSTS)
v2013.01.01 - struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;

Newb question, but I should be able to add an offset to correct this issue right?

Thanks

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p151609.html
Sent from the U-Boot mailing list archive at Nabble.com.

#11 lore raw
Quoted 36 lines · txcotrader

After looking deeper I've found a difference in register values when performing drivers/i2c/ppc4xx_i2c.c->i2c_transfer function.

v1.7.02 code yields:

/* Transfer is in progress

         * we have to wait for upto 5 bytes of data
         * 1 byte chip address+r/w bit then bc bytes
         * of data.
         * udelay(10) is 1 bit time at 100khz
         * Doubled for slop. 20 is too small.
         */
        i = 2*5*8;
        do {
            /* Get status */
            status = in_8((u8 *)IIC_STS);
            printf("gd_ do status->i = %d, status = %d\n", i, status);
            udelay(20);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i >

0));

gd_ do status->i = 80, status = 40

v2013.01.01 Yields:

        i = 2 * 5 * 8;
        do {
            /* Get status */
            status = in_8(&i2c->sts);
            printf("gd_ do status->i = %d, status = %d\n", i, status);
            udelay(10);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) &&
             (i > 0));
Quoted 8 lines

gd_ do status->i = 80, status = 40

v1.7.02 - include/4xx_i2c.h:#define IIC_STS (I2C_REGISTERS_BASE_ADDRESS+IICSTS)
v2013.01.01 - struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;

Newb question, but I should be able to add an offset to correct this issue right?

The resulting addresses should be the same. The old version uses the offset via a define and the new one the (recommended) struct access to the register. I suggest you print the resulting address to verify that it really is the same.

Thanks,
Stefan

author
#12 lore raw

Thanks for the suggestion Stefan, the addresses are definitely different:

v2013.01.01: I2C_BASE_ADDR = ef600400

v1.7.02: IIC_STS = ef600408

Would you suggest not using the default drivers and configure GPIO or could this possibly be a bug in the new version?

Thanks,
Greg

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p151799.html
Sent from the U-Boot mailing list archive at Nabble.com.

#13 lore raw
Quoted 3 lines · txcotrader

Thanks for the suggestion Stefan, the addresses are definitely different:

v2013.01.01: I2C_BASE_ADDR = ef600400

Thats the base address of the struct. Please check the address of the STS register instead (&i2c->sts). It it still different from the IIC_STS define from the old version?

Quoted 4 lines

v1.7.02: IIC_STS = ef600408

Would you suggest not using the default drivers and configure GPIO or could this possibly be a bug in the new version?

If the addresses really are different, then its a bug. Most likely only for the 440SX (correct?). I suggest you dig into this a bit deeper to find the root cause for this address difference.

Hope this helps,
Stefan

author
#14 lore raw
In reply to Stefan Roese

Sefan,

Thanks for the suggestion, I2C_BASE_ADDR is the same in both versions. After doing some more digging, I can see why v2013.01.01 is not passing i2c_transfer. The following routine yields different results in the 2 versions:

v2013.01.01-

   do {
            /* Get status */
            status = in_8(&i2c->sts);
            printf("gd_ do status->i = %x, status = %d, IIC_STS = %x\n", i,
status, &i2c->sts);
            udelay(10);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) &&
             (i > 0));

Result: gd_ do status->i = 80, status = 4, IIC_STS = ef600408

v1.7.02-

   do {
            /* Get status */
            status = in_8((u8 *)IIC_STS);
            printf("gd_ do status->i = %d, status = %d, IIC_STS = %x\n", i,
status, IIC_STS);
            udelay(10);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i >

0));

Result: gd_ do status->i = 80, status = 40, IIC_STS = ef600408

So in v2013.01.01 (status & IIC_STS_ERR) == 1, versus a (status & IIC_STS_ERR) == 0 in v1.7.02. Am I missing some sort of offset config someplace? Once again, any help is greatly appreciated.

Thank you!
Greg

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p151814.html
Sent from the U-Boot mailing list archive at Nabble.com.

#15 lore raw

Greg,

Quoted 27 lines · txcotrader

Thanks for the suggestion, I2C_BASE_ADDR is the same in both versions. After doing some more digging, I can see why v2013.01.01 is not passing i2c_transfer. The following routine yields different results in the 2 versions:

v2013.01.01-

   do {
            /* Get status */
            status = in_8(&i2c->sts);
            printf("gd_ do status->i = %x, status = %d, IIC_STS = %x\n", i,
status, &i2c->sts);
            udelay(10);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) &&
             (i > 0));

Result: gd_ do status->i = 80, status = 4, IIC_STS = ef600408

v1.7.02-

   do {
            /* Get status */
            status = in_8((u8 *)IIC_STS);
            printf("gd_ do status->i = %d, status = %d, IIC_STS = %x\n", i,
status, IIC_STS);
            udelay(10);
            i--;
        } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i >
Quoted 7 lines

0));

Result: gd_ do status->i = 80, status = 40, IIC_STS = ef600408

So in v2013.01.01 (status & IIC_STS_ERR) == 1, versus a (status & IIC_STS_ERR) == 0 in v1.7.02. Am I missing some sort of offset config someplace? Once again, any help is greatly appreciated.

So look into the manual to check what exactly these IIC_STS bits/differences mean. 0x4 versus 0x40. This might give you a hint. Perhaps some clocks missing? Not sure.

Which PPC4xx variant are you using again? 460SX?

Thanks,
Stefan

author
#16 lore raw

Stefan,

Yes, I am working with a 460SX and a board based off of AMCC Eiger (unsupported as of 2010).

IICx_STS Register settings:
04 = MDBF Full = Master data buffer contains data 40 = IRQA Active = An IIC interrrupt has been sent to the UIC

I'm clearing the IIC register early on in my code:
mtdcr(UIC0SR, 0xffffffff); /* clear all */

    mtdcr(UIC0ER, 0x00000000);  /* disable all */
    mtdcr(UIC0CR, 0x00000005);  /* ATI & UIC1 crit are critical */
    mtdcr(UIC0PR, 0xffffffff);  /* per ref-board manual */
    mtdcr(UIC0TR, 0x00000000);  /* per ref-board manual */
    mtdcr(UIC0VR, 0x00000000);  /* int31 highest, base=0x000 */
    mtdcr(UIC0SR, 0xffffffff);  /* clear all */
    mtdcr(UIC1SR, 0xffffffff);  /* clear all */
    mtdcr(UIC1ER, 0x00000000);  /* disable all */
    mtdcr(UIC1CR, 0x00000000);  /* all non-critical */
    mtdcr(UIC1PR, 0xffffffff);  /* per ref-board manual */
    mtdcr(UIC1TR, 0x00000000);  /* per ref-board manual */
    mtdcr(UIC1VR, 0x00000000);  /* int31 highest, base=0x000 */
    mtdcr(UIC1SR, 0xffffffff);  /* clear all */

I'm really not sure what to look for at this point, any additional tips you might have would be extremely helpful. I truly appreciate your help to this point.

Thanks,
Greg

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p151862.html
Sent from the U-Boot mailing list archive at Nabble.com.

#17 lore raw

Greg,

Quoted 2 lines · txcotrader

Yes, I am working with a 460SX and a board based off of AMCC Eiger (unsupported as of 2010).

460SX is quite untested these days I'm afraid. I don't have such a board here as well.

Quoted 13 lines

IICx_STS Register settings:
04 = MDBF Full = Master data buffer contains data 40 = IRQA Active = An IIC interrrupt has been sent to the UIC

I'm clearing the IIC register early on in my code:
mtdcr(UIC0SR, 0xffffffff); /* clear all */

    mtdcr(UIC0ER, 0x00000000);  /* disable all */
    mtdcr(UIC0CR, 0x00000005);  /* ATI & UIC1 crit are critical */
    mtdcr(UIC0PR, 0xffffffff);  /* per ref-board manual */
    mtdcr(UIC0TR, 0x00000000);  /* per ref-board manual */
    mtdcr(UIC0VR, 0x00000000);  /* int31 highest, base=0x000 */
    mtdcr(UIC0SR, 0xffffffff);  /* clear all */
Quoted 7 lines
    mtdcr(UIC1SR, 0xffffffff);  /* clear all */
    mtdcr(UIC1ER, 0x00000000);  /* disable all */
    mtdcr(UIC1CR, 0x00000000);  /* all non-critical */
    mtdcr(UIC1PR, 0xffffffff);  /* per ref-board manual */
    mtdcr(UIC1TR, 0x00000000);  /* per ref-board manual */
    mtdcr(UIC1VR, 0x00000000);  /* int31 highest, base=0x000 */
    mtdcr(UIC1SR, 0xffffffff);  /* clear all */

Ughh! This is not IIC (I2C) but UIC released code. So its for the interrupt controller and not I2C controller. But nevertheless this should not matter.

Quoted 3 lines

I'm really not sure what to look for at this point, any additional tips you might have would be extremely helpful. I truly appreciate your help to this point.

As mentioned above I don't have such a board here, so I can't really test anything. Sorry.

Best regards,
Stefan

author
#18 lore raw

Stefan,

I know it's been awhile, but I do appreciate your previous help. I took some time off to complete other projects, now I'm back working on finishing this port. During the boot I'm seeing the value of &i2c->extsts is either 0x40 or 0x60 which equates to lost arbitration or lost arbitration and incomplete transfer. Have you seen this type of error based on a misconfiguration? Any help you're willing to provide is greatly appreciated.

Thanks,
Greg

--
View this message in context: http://u-boot.10912.n7.nabble.com/PPC4XX-Custom-Board-Failing-to-read-I2C-tp151298p159975.html
Sent from the U-Boot mailing list archive at Nabble.com.

#19 lore raw

Greg,

Quoted 6 lines · txcotrader

I know it's been awhile, but I do appreciate your previous help. I took some time off to complete other projects, now I'm back working on finishing this port. During the boot I'm seeing the value of &i2c->extsts is either 0x40 or 0x60 which equates to lost arbitration or lost arbitration and incomplete transfer. Have you seen this type of error based on a misconfiguration? Any help you're willing to provide is greatly appreciated.

Sorry, I have no idea why this could be the case. Do you have another 4xx based board (some AMCC/APM eval board) to compare the "extsts" register value? This might give you a clue.

Thanks,
Stefan