Dear all, SZ, great initiative. Gedare and Sebastian have commented.
For my part, can I just check - the implementation is supposed to be generic to i2c devices, correct? If so, can you explain what read_eeprom is for? Is it just as demo? Is the code generic otherwise? Cheers, Ben On 03/14/2017 10:05 AM, Sichen Zhao wrote: > --- > c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c | 684 > ++++++++++++++++++++++++++++-- > c/src/lib/libbsp/arm/beagle/include/i2c.h | 18 +- > cpukit/dev/i2c/eeprom.c | 24 +- > testsuites/samples/i2c0/init.c | 98 ++++- > 4 files changed, 777 insertions(+), 47 deletions(-) > > diff --git a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c > b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c > index 6b790e5..6a22125 100644 > --- a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c > +++ b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c > @@ -21,11 +21,23 @@ > #include <bsp/bbb-gpio.h> > #include <rtems/score/assert.h> > > +#define u16 unsigned int > + > +static int am335x_i2c_set_clock(i2c_bus *base, unsigned long clock); > +static void omap24_i2c_init(i2c_bus *base); > +static void flush_fifo(i2c_bus *base); > +static int wait_for_bb(i2c_bus *base); > +static int omap24_i2c_probe(i2c_bus *base); > +static u16 wait_for_event(i2c_bus *base); > +static int am335x_i2c_read(i2c_bus *base, unsigned char chip, uint addr, int > alen, unsigned char *buffer, > + int len); > +static int read_eeprom(i2c_bus *base,struct am335x_baseboard_id *header); > +static int am335x_i2c_write(i2c_bus *base, unsigned char chip, uint addr,int > alen, unsigned char *buffer, > + int len); > /* > static bool am335x_i2c_pinmux(bbb_i2c_bus *bus) > { > bool status =true; > - > // We will check i2c_bus_id in am335x_i2c_bus_register > // Apart from mode and pull_up register what about SCREWCTRL & RXACTIVE > ?? > if (bus->i2c_bus_id == I2C1) { > @@ -48,9 +60,7 @@ static bool am335x_i2c_pinmux(bbb_i2c_bus *bus) > /* ref. Table 21-4 I2C Clock Signals */ > /* > For I2C1/2 > - > Interface clock - 100MHz - CORE_LKOUTM4 / 2 - pd_per_l4ls_gclk > - > Functional clock - 48MHz - PER_CLKOUTM2 / 4 - pd_per_ic2_fclk > */ > > @@ -74,7 +84,6 @@ state. Functional clocks are guarantied to stay present. As > long as in > this configuration, power domain sleep transition cannot happen.*/ > /* REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKCTRL) |= > AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE; > - > while((REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKCTRL) & > AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE) != > AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE); > */ > @@ -86,30 +95,29 @@ this configuration, power domain sleep transition cannot > happen.*/ > if (bus->i2c_bus_id == I2C1) { > REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C1_CLKCTRL) |= > AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE; > - > while(REG((AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C1_CLKCTRL) & > AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE) != > AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE); > } else if (bus->i2c_bus_id == I2C2) { > REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C2_CLKCTRL) |= > AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE; > - > while(REG((AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C2_CLKCTRL) & > AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE) != > AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE); > - > while(!(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) & > (AM335X_CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK | > AM335X_CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_I2C_FCLK))); > - > } > } > */ > > static void am335x_i2c0_pinmux(bbb_i2c_bus *bus) > { > - REG(bus->regs + AM335X_CONF_I2C0_SDA) = > + printf("0x44e10000 + AM335X_CONF_I2C0_SDA:%x\n",0x44e10000 + > AM335X_CONF_I2C0_SDA); > + printf("bus->regs:%x\n", bus->regs); > + > + REG(0x44e10000 + AM335X_CONF_I2C0_SDA) = > (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN); > > - REG(bus->regs + AM335X_CONF_I2C0_SCL) = > + REG(0x44e10000 + AM335X_CONF_I2C0_SCL) = > (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN); > } > > @@ -314,14 +322,29 @@ void am335x_i2c_init(bbb_i2c_bus *bus, uint32_t > input_clock) > static bool am335x_i2c_busbusy(volatile bbb_i2c_regs *regs) > { > bool status; > - > - if (REG(®s->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB) > + unsigned short stat; > + int timeout = I2C_TIMEOUT; > + > + REG(®s->BBB_I2C_IRQSTATUS)=0xffff; > + > printf("REG(®s->BBB_I2C_IRQSTATUS_RAW):%x\n",REG(®s->BBB_I2C_IRQSTATUS_RAW) > ); > + // printf("%x\n",0x1400 & 0x1000 ); > + printf("REG(®s->BBB_I2C_IRQSTATUS_RAW) & > AM335X_I2C_IRQSTATUS_RAW_BB:%x\n",(REG(®s->BBB_I2C_IRQSTATUS_RAW) & > AM335X_I2C_IRQSTATUS_RAW_BB)); > +while(stat =( REG(®s->BBB_I2C_IRQSTATUS_RAW) & > AM335X_I2C_IRQSTATUS_RAW_BB) && timeout--) > { > - status = true; > - } else { > - status = false; > + > +REG(®s->BBB_I2C_IRQSTATUS)=stat; > + udelay(20); > + > + } > + > + if (timeout <= 0) { > + printf("Timed out in wait_for_bb: status=%04x\n", > + stat); > + return 1; > } > - return status; > + REG(®s->BBB_I2C_IRQSTATUS)=0xffff; /* clear delayed stuff*/ > + return 0; > + > } > > static void am335x_i2c_reset(bbb_i2c_bus *bus) > @@ -330,9 +353,27 @@ static void am335x_i2c_reset(bbb_i2c_bus *bus) > printk("reset bus->reg is %x \n",bus->regs); > /* Disable I2C module at the time of initialization*/ > /*Should I use write32 ?? I guess mmio_clear is correct choice here*/ > + REG(®s->BBB_I2C_CON)=0x00; > printk("inside BBB_I2C_CON value is %x \n",®s->BBB_I2C_CON); > - mmio_clear((®s->BBB_I2C_CON),AM335X_I2C_CON_I2C_EN); > - mmio_clear((®s->BBB_I2C_SYSC),AM335X_I2C_SYSC_AUTOIDLE); > + REG(®s->BBB_I2C_SYSC)= 0x2; > +// mmio_clear((®s->BBB_I2C_CON),AM335X_I2C_CON_I2C_EN); > + > + REG(®s->BBB_I2C_CON)= AM335X_I2C_CON_I2C_EN; > + > + while((REG(®s->BBB_I2C_SYSS) &I2C_SYSS_RDONE)==0) //wait reset done > + { > + udelay(100); > + > + } > + > + REG(®s->BBB_I2C_CON)=0x00; > + > + am335x_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT); > + > + REG(®s->BBB_I2C_CON)= AM335X_I2C_CON_MST | AM335X_I2C_CON_I2C_EN; > + > +// mmio_clear((®s->BBB_I2C_SYSC),AM335X_I2C_SYSC_AUTOIDLE); > + > //REG(bus->regs + AM335X_I2C_CON) &= ~(AM335X_I2C_CON_I2C_EN); > //REG(bus->regs + AM335X_I2C_SYSC) &= ~(AM335X_I2C_SYSC_AUTOIDLE); > > @@ -385,6 +426,7 @@ static unsigned int am335x_i2c_intrawstatus(volatile > bbb_i2c_regs *regs) > > static void am335x_i2c_masterint_enable(volatile bbb_i2c_regs *regs, > unsigned int flag) > { > + printf("am335x_i2c_masterint_enable func\n"); > REG(®s->BBB_I2C_IRQENABLE_SET) |= flag; > } > > @@ -401,6 +443,7 @@ static void am335x_int_clear(volatile bbb_i2c_regs *regs, > unsigned int flag) > > static void am335x_clean_interrupts(volatile bbb_i2c_regs *regs) > { > + printf("am335x_clean_interrupts func\n"); > am335x_i2c_masterint_enable(regs,0x7FFF); > am335x_int_clear(regs,0x7FFF); > am335x_i2c_masterint_disable(regs,0x7FFF); > @@ -412,30 +455,69 @@ static void am335x_i2c_setup_read_transfer(bbb_i2c_bus > *bus, volatile bbb_i2c_re > volatile unsigned int no_bytes; > //am335x_i2c_masterint_enable(regs, AM335X_I2C_INT_RECV_READY); > // No of data to be transmitted at a time > + > + > +//bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > +// volatile bbb_i2c_regs *regs = bus->regs; > + struct am335x_baseboard_id header; > + > + omap24_i2c_probe(&bus->base); > + read_eeprom(&bus->base,&header); > + > +/* > REG(®s->BBB_I2C_CNT) = 0x02; > no_bytes = REG(®s->BBB_I2C_CNT); > > + // Set Slave address & Master enable, bring out of reset > + REG(®s->BBB_I2C_SA) = msgs->addr; > + printf("slave address : %x\n",REG(®s->BBB_I2C_SA)); > + > + > // I2C Controller in Master Mode > - REG(®s->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN | > AM335X_I2C_CON_START | AM335X_I2C_CON_MST; > + REG(®s->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_MST | > AM335X_I2C_CON_START | AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_STOP; > printk("set master in transmission mode %x \n",REG(®s->BBB_I2C_CON)); > > - // Set Slave address & Master enable, bring out of reset > - REG(®s->BBB_I2C_SA) = msgs->addr; > - printf("slave address : %x\n",REG(®s->BBB_I2C_SA)); > +while(am335x_i2c_busbusy(regs) != 0); > + printk("bus is free \n"); > + > + > + > > // clear status of all interrupts > am335x_clean_interrupts(regs); > printk("\n set memory address to read\n"); > > // transmit interrupt is enabled > + > am335x_i2c_masterint_enable(regs,AM335X_I2C_IRQSTATUS_XRDY); > printk("Enable transmit interrupt \n"); > + > + > + > //start condition > - REG(®s->BBB_I2C_CON) |= AM335X_I2C_CON_START; > + REG(®s->BBB_I2C_CON) |= AM335X_I2C_CON_START | AM335X_I2C_CON_I2C_EN; > printk("start transmission \n"); > - while(am335x_i2c_busbusy(regs) == 0); > - printk("bus is free \n"); > + > printk("CNT : %x\n", no_bytes); > + printf("BBB_I2C_DATA:%x\n", readb(®s->BBB_I2C_DATA)); > + > +writeb(0x5,®s->BBB_I2C_DATA); > +printf("(0x50 >> 8)& 0xff:%x\n",(0x50 >> 8)& 0xff); > +printf("REG(®s->BBB_I2C_DATA):%x\n",readb(®s->BBB_I2C_DATA) ); > +printf("®s->BBB_I2C_DATA:%x\n",®s->BBB_I2C_DATA); > +//REG(®s->BBB_I2C_IRQSTATUS)=AM335X_I2C_IRQSTATUS_XRDY; > + > +udelay(10); > + > +writeb(0x0,®s->BBB_I2C_DATA); > +//REG(®s->BBB_I2C_DATA)= ( (0x50 >> 0)& 0xff); > +printf("(0x50 >> 0)& 0xff:%x\n",(0x50 >> 0)& 0xff); > +printf("REG(®s->BBB_I2C_DATA):%x\n",readb(®s->BBB_I2C_DATA) ); > + > +REG(®s->BBB_I2C_IRQSTATUS)=AM335X_I2C_IRQSTATUS_XRDY; > + > + > + // no_bytes = REG(®s->BBB_I2C_CNT); > while(0 != no_bytes); > printk("total msg count for tranmission is zero \n"); > while( !(am335x_i2c_intrawstatus(regs) & (AM335X_I2C_IRQSTATUS_ARDY))); > @@ -464,6 +546,7 @@ static void am335x_i2c_setup_read_transfer(bbb_i2c_bus > *bus, volatile bbb_i2c_re > REG(®s->BBB_I2C_CON) |= AM335X_I2C_CON_START; > } > while(am335x_i2c_busbusy(regs) == 0); > + */ > printk("Exit read transfer\n"); > } > > @@ -570,11 +653,16 @@ static void am335x_i2c_setup_transfer(bbb_i2c_bus *bus, > volatile bbb_i2c_regs *r > } > > regs = bus->regs; > - > - REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_TXFIFO_CLR; > - REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_RXFIFO_CLR; > - am335x_i2c_set_address_size(msgs,regs); > - bus->read = ((bus->read == true) ? 0:1); > + printf("REG(®s->BBB_I2C_DATA):%x\n",REG(®s->BBB_I2C_DATA) ); > + // REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_TXFIFO_CLR; > + // REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_RXFIFO_CLR; > +printf("REG(®s->BBB_I2C_DATA):%x\n",REG(®s->BBB_I2C_DATA) ); > + > + // am335x_i2c_set_address_size(msgs,regs); > +bus->read = (msgs->flags & I2C_M_RD) != 0; > + > +printf("bus->read:%d\n",bus->read ); > + //bus->read = ((bus->read == true) ? 0:1); > bus->already_transferred = (bus->read == true) ? 0 : 1; > > if (bus->read) { > @@ -652,7 +740,7 @@ static int am335x_i2c_transfer(i2c_bus *base, i2c_msg > *msgs, uint32_t msg_count) > bbb_i2c_bus *bus = (bbb_i2c_bus *)base; > volatile bbb_i2c_regs *regs; > uint32_t i; > - printk("\n enter transfer "); > + printk("\n enter transfer\n "); > rtems_task_wake_after(1); > > > @@ -665,20 +753,23 @@ static int am335x_i2c_transfer(i2c_bus *base, i2c_msg > *msgs, uint32_t msg_count) > return -EINVAL; > } > } > - > + printf("bus->regs:%x\n",bus->regs ); > bus->msgs = &msgs[0]; > bus->msg_todo = msg_count; > printk("total msg = msg_count : %x \n",bus->msg_todo); > bus->current_msg_todo = msgs[0].len;// current data size > - bus->current_msg_byte = msgs[0].buf;// current data > + //bus->current_msg_byte = msgs[0].buf;// current data > printk("\n current_msg_todo %x \n ",msgs[0].len); > printk("\n current_msg_byte %x \n ",msgs[0].buf); > + //printf("8011A5CC:%x\n", *(unsigned int *)(0x8011A5CC) ); > bus->task_id = rtems_task_self(); > > regs = bus->regs; > - am335x_i2c_setup_transfer(bus,regs); > - REG(®s->BBB_I2C_IRQENABLE_SET) = BBB_I2C_IRQ_USED; > > + // REG(®s->BBB_I2C_IRQENABLE_SET) = BBB_I2C_IRQ_USED; > + am335x_i2c_setup_transfer(bus,regs); > + > +/* > sc = rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout); > // If timeout then return timeout error > if (sc != RTEMS_SUCCESSFUL) { > @@ -688,7 +779,9 @@ static int am335x_i2c_transfer(i2c_bus *base, i2c_msg > *msgs, uint32_t msg_count) > > return -ETIMEDOUT; > } > + */ > printk("exit transfer\n"); > + > // return bus->regs->BBB_I2C_IRQSTATUS == 0 ? 0 : -EIO; > return 0; > } > @@ -700,19 +793,28 @@ static int am335x_i2c_set_clock(i2c_bus *base, unsigned > long clock) > uint32_t prescaler,divider; > > printk("set clock start\n"); > + REG(®s->BBB_I2C_CON)=0; > + > prescaler = (BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK) -1; > + printf("prescaler:%d\n",prescaler ); > printk("PSC offset %x \n ",®s->BBB_I2C_PSC); > printk("PSC offset %x \n", &bus->regs->BBB_I2C_PSC); > //mmio_write((®s->BBB_I2C_PSC), prescaler); > REG(&bus->regs->BBB_I2C_PSC) = prescaler; > > divider = BBB_I2C_INTERNAL_CLK/(2*clock); > + printf("divider:%d\n", divider); > printk("SCLL offset %x \n",&bus->regs->BBB_I2C_SCLL); > //mmio_write((®s->BBB_I2C_SCLL), (divider - 7)); > REG(&bus->regs->BBB_I2C_SCLL) = (divider - 7); > //mmio_write((®s->BBB_I2C_SCLH), (divider - 5)); > printk("SCHL offset %x\n",&bus->regs->BBB_I2C_SCLH); > REG(&bus->regs->BBB_I2C_SCLH) = (divider - 5); > + > + REG(®s->BBB_I2C_CON)=I2C_CON_EN; > + > +writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); /* clear all pending status > */ > + > printk("set clock end \n"); > return 0; > } > @@ -729,6 +831,8 @@ static void am335x_i2c_destroy(i2c_bus *base) > i2c_bus_destroy_and_free(&bus->base); > } > > + > + > int am335x_i2c_bus_register( > const char *bus_path, > uintptr_t register_base, > @@ -751,14 +855,15 @@ int am335x_i2c_bus_register( > bus->regs = (volatile bbb_i2c_regs *) register_base; > > // 1. Enable clock for I2CX > - I2C0ModuleClkConfig(); > + I2C0ModuleClkConfig(); > // 2. pinmux setup > am335x_i2c0_pinmux(bus); > // 3. RESET : Disable Master, autoideal > - am335x_i2c_reset(bus); > + // am335x_i2c_reset(bus); > // 4. configure bus speed > bus->input_clock = input_clock; // By default 100KHz. Normally pass 100KHz > as argument > > +/* > printk("Before set clock \n"); > err = am335x_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT); > > @@ -768,12 +873,16 @@ int am335x_i2c_bus_register( > rtems_set_errno_and_return_minus_one(-err); > } > bus->irq = irq; > - > + */ > +omap24_i2c_init(&bus->base); > + > //bring I2C out of reset > > - REG(&bus->regs->BBB_I2C_CON) |= AM335X_I2C_CON_I2C_EN; > +//printf("REG(®s->BBB_I2C_IRQSTATUS):%x\n",REG(&bus->regs->BBB_I2C_IRQSTATUS)); > + // REG(&bus->regs->BBB_I2C_CON) |= AM335X_I2C_CON_I2C_EN; > > // 5. Start interrupt service routine & one interrupt at a time > +/* > sc = rtems_interrupt_handler_install( > irq, > "BBB I2C", > @@ -787,6 +896,7 @@ int am335x_i2c_bus_register( > > rtems_set_errno_and_return_minus_one(EIO); > } > + */ > // 6. start transfer for reading and writing > bus->base.transfer = am335x_i2c_transfer; > bus->base.set_clock = am335x_i2c_set_clock; > @@ -794,3 +904,499 @@ int am335x_i2c_bus_register( > printk("exit register\n"); > return i2c_bus_register(&bus->base,bus_path); > } > + > + > + > + > + > + > +static void omap24_i2c_init(i2c_bus *base) > +{ > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + struct am335x_baseboard_id header; > + > + int timeout = I2C_TIMEOUT; > + int deblock = 1; > +printf("omap24_i2c_init func!!!!!!\n"); > +retry: > + if (readw(&bus->regs->BBB_I2C_CON) & I2C_CON_EN) { > + writew(0, &bus->regs->BBB_I2C_CON); > + udelay(50000); > + } > + > + writew(0x2, &bus->regs->BBB_I2C_SYSC); /* for ES2 after soft reset */ > + udelay(1000); > + > + writew(I2C_CON_EN, &bus->regs->BBB_I2C_CON); > + while (!(readw(&bus->regs->BBB_I2C_SYSS) & I2C_SYSS_RDONE) && timeout--) { > + if (timeout <= 0) { > + puts("ERROR: Timeout in soft-reset\n"); > + return; > + } > + udelay(1000); > + } > + > +am335x_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT); > + > + /* own address */ > + writew(1, &bus->regs->BBB_I2C_OA); > + > +//#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) > + /* > + * Have to enable interrupts for OMAP2/3, these IPs don't have > + * an 'irqstatus_raw' register and we shall have to poll 'stat' > + */ > + // writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE > | I2C_IE_AL_IE, &i2c_base->ie); > +//#endif > + udelay(1000); > + flush_fifo(&bus->base); > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); > + > + /* Handle possible failed I2C state */ > + if (wait_for_bb(&bus->base)) > + if (deblock == 1) { > + > + //omap24_i2c_deblock(&bus->base); > + printf("deblock\n"); > + deblock = 0; > + goto retry; > + } > + > + > + // omap24_i2c_probe(&bus->base); > + // read_eeprom(&bus->base,&header); > + > +} > + > + > +static void flush_fifo(i2c_bus *base) > +{ > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + > + u16 stat; > +printf("flush_fifo\n"); > + /* > + * note: if you try and read data when its not there or ready > + * you get a bus error > + */ > + while (1) { > + stat = readw(&bus->regs->BBB_I2C_IRQSTATUS); > + if (stat == I2C_STAT_RRDY) { > + readb(&bus->regs->BBB_I2C_DATA); > + writew(I2C_STAT_RRDY, &bus->regs->BBB_I2C_IRQSTATUS); > + udelay(1000); > + } else > + break; > + } > +} > + > + > +static int wait_for_bb(i2c_bus *base) > +{ > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + > + int timeout = I2C_TIMEOUT; > + u16 stat; > +printf("wait_for_bb\n"); > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); /* clear current > interrupts...*/ > +//printf("test1\n"); > + /* Read RAW status */ > +//printf("%x\n", readw(&bus->regs->BBB_I2C_IRQSTATUS_RAW) & I2C_STAT_BB); > + while ((stat = readw(&bus->regs->BBB_I2C_IRQSTATUS_RAW) & > + I2C_STAT_BB) && timeout--) { > + > + writew(stat, &bus->regs->BBB_I2C_IRQSTATUS); > + udelay(200); > + } > + > + if (timeout <= 0) { > + printf("Timed out in wait_for_bb: status=%04x\n", > + stat); > + return 1; > + } > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); /* clear delayed stuff*/ > + return 0; > +} > + > + > +static int omap24_i2c_probe(i2c_bus *base) > +{ > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + unsigned char chip = 0x50; > + u16 status; > + int res = 1; /* default = fail */ > + > +printf("omap24_i2c_probe\n"); > + if (chip == readw(&bus->regs->BBB_I2C_OA)) > + return res; > + > + /* Wait until bus is free */ > + if (wait_for_bb(&bus->base)) > + return res; > + > + /* No data transfer, slave addr only */ > + writew(chip, &bus->regs->BBB_I2C_SA); > + /* Stop bit needed here */ > + writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | > + I2C_CON_STP, &bus->regs->BBB_I2C_CON); > + > + status = wait_for_event(&bus->base); > + > + if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) { > + /* > + * With current high-level command implementation, notifying > + * the user shall flood the console with 127 messages. If > + * silent exit is desired upon unconfigured bus, remove the > + * following 'if' section: > + */ > + if (status == I2C_STAT_XRDY) > + printf("i2c_probe: pads on bus probably not configured > (status=0x%x)\n",status); > + > + goto pr_exit; > + } > + > + /* Check for ACK (!NAK) */ > + if (!(status & I2C_STAT_NACK)) { > + printf("Device found\n"); > + res = 0; /* Device found */ > + udelay(200);/* Required by AM335X in SPL */ > + /* Abort transfer (force idle state) */ > + writew(I2C_CON_MST | I2C_CON_TRX, &bus->regs->BBB_I2C_CON); /* Reset */ > + udelay(1000); > + writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX | > + I2C_CON_STP, &bus->regs->BBB_I2C_CON); /* STP */ > + } > +pr_exit: > + flush_fifo(&bus->base); > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); > + return res; > +} > + > + > +static u16 wait_for_event(i2c_bus *base) > +{ > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + > + u16 status; > + int timeout = I2C_TIMEOUT; > +//printf("wait_for_event \n"); > + do { > + udelay(200); > + > + /* Read RAW status */ > + status = readw(&bus->regs->BBB_I2C_IRQSTATUS_RAW); > + > + } while (!(status & > + (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | > + I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | > + I2C_STAT_AL)) && timeout--); > + > + if (timeout <= 0) { > + printf("Timed out in wait_for_event: status=%04x\n", > + status); > + /* > + * If status is still 0 here, probably the bus pads have > + * not been configured for I2C, and/or pull-ups are missing. > + */ > + printf("Check if pads/pull-ups of bus are properly configured\n"); > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); > + status = 0; > + } > + > + return status; > +} > + > + > + > + > +static int am335x_i2c_read(i2c_bus *base, unsigned char chip, uint addr, int > alen, unsigned char *buffer, > + int len) > +{ > + > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + int i2c_error = 0; > + int i=0; > + u16 status; > +printf("am335x_i2c_read\n"); > + if (alen < 0) { > + puts("I2C read: addr len < 0\n"); > + return 1; > + } > + if (len < 0) { > + puts("I2C read: data len < 0\n"); > + return 1; > + } > + if (buffer == NULL) { > + puts("I2C read: NULL pointer passed\n"); > + return 1; > + } > + > + if (alen > 2) { > + printf("I2C read: addr len %d not supported\n", alen); > + return 1; > + } > + > + if (addr + len > (1 << 16)) { > + puts("I2C read: address out of range\n"); > + return 1; > + } > + > + /* Wait until bus not busy */ > + if (wait_for_bb(&bus->base)) > + return 1; > +//printf("test2\n"); > + /* Zero, one or two bytes reg address (offset) */ > + writew(alen, &bus->regs->BBB_I2C_CNT); > + /* Set slave address */ > + writew(chip, &bus->regs->BBB_I2C_SA); > +//printf("test3\n"); > + if (alen) { > + /* Must write reg offset first */ > + > + /* Stop - Start (P-S) */ > + writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP | > + I2C_CON_TRX, &bus->regs->BBB_I2C_CON); > + > + /* Send register offset */ > + while (1) { > + status = wait_for_event(&bus->base); > + printf("status:%x\n",status ); > + /* Try to identify bus that is not padconf'd for I2C */ > + if (status == I2C_STAT_XRDY) { > + i2c_error = 2; > + printf("i2c_read (addr phase): pads on bus probably not configured > (status=0x%x)\n", > + status); > + goto rd_exit; > + } > + if (status == 0 || (status & I2C_STAT_NACK)) { > + i2c_error = 1; > + printf("i2c_read: error waiting for addr ACK (status=0x%x)\n", > + status); > + goto rd_exit; > + } > + if (alen) { > + if (status & I2C_STAT_XRDY) { > + // printf("alen:%d\n",alen ); > + alen--; > + // printf("alen:%d\n",alen ); > + // printf("addr:%x\n",addr ); > + // printf("(addr >> (8 * alen)) & 0xff:%x\n",(addr >> (8 * alen)) & > 0xff ); > + /* Do we have to use byte access? */ > + writeb((addr >> (8 * alen)) & 0xff, > + &bus->regs->BBB_I2C_DATA); > + writew(I2C_STAT_XRDY, &bus->regs->BBB_I2C_IRQSTATUS); > + } > + } > + if (status & I2C_STAT_ARDY) { > + writew(I2C_STAT_ARDY, &bus->regs->BBB_I2C_IRQSTATUS); > + break; > + } > + } > + } > + /* Set slave address */ > + writew(chip, &bus->regs->BBB_I2C_SA); > + /* Read len bytes from slave */ > + writew(len, &bus->regs->BBB_I2C_CNT); > + /* Need stop bit here */ > + writew(I2C_CON_EN | I2C_CON_MST | > + I2C_CON_STT | I2C_CON_STP, > + &bus->regs->BBB_I2C_CON); > +//printf("test4\n"); > + > + > + /* Receive data */ > + while (1) { > + status = wait_for_event(&bus->base); > + // printf("test 5\n"); > + /* > + * Try to identify bus that is not padconf'd for I2C. This > + * state could be left over from previous transactions if > + * the address phase is skipped due to alen=0. > + */ > + if (status == I2C_STAT_XRDY) { > + i2c_error = 2; > + printf("i2c_read (data phase): pads on bus probably not configured > (status=0x%x)\n", > + status); > + goto rd_exit; > + } > + if (status == 0 || (status & I2C_STAT_NACK)) { > + // printf("i2c_error = 1\n"); > + i2c_error = 1; > + goto rd_exit; > + } > + if (status & I2C_STAT_RRDY) { > + char temp; > + temp=readb(&bus->regs->BBB_I2C_DATA); > + *buffer++ =temp; > + > + *bus->msgs[0].buf++=temp; > + // (*(uint8_t *) bus->current_msg_byte[0]) = > readb(&bus->regs->BBB_I2C_DATA) & 0xFF; > + i++; > + writew(I2C_STAT_RRDY, &bus->regs->BBB_I2C_IRQSTATUS); > + } > + if (status & I2C_STAT_ARDY) { > + writew(I2C_STAT_ARDY, &bus->regs->BBB_I2C_IRQSTATUS); > + break; > + } > + } > + > +rd_exit: > +//printf("rd_exit\n"); > +//printf("i2c_error:%d\n",i2c_error); > + flush_fifo(&bus->base); > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); > + return i2c_error; > +} > + > + > + > +static int read_eeprom(i2c_bus *base,struct am335x_baseboard_id *header) > +{ > + > +bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > +printf("sizeof(struct am335x_baseboard_id):%d\n",sizeof(struct > am335x_baseboard_id) ); > +//printf("sizeof(struct am335x_baseboard_id):%d\n",sizeof(unsigned int) ); > +//printf("sizeof(struct am335x_baseboard_id):%d\n",sizeof(unsigned int) ); > + am335x_i2c_read(&bus->base,0x50,0,2,(unsigned char *)header,sizeof(struct > am335x_baseboard_id)); > +/* > +printf("am335x_i2c_read end\n"); > + printf("header->magic:%x\n", header->magic); > + printf("header->name[0]:%x\n", header->name[0]); > + printf("header->name[1]:%x\n", header->name[1]); > + printf("header->name[2]:%x\n", header->name[2]); > + printf("header->name[3]:%x\n", header->name[3]); > + printf("header->name[4]:%x\n", header->name[4]); > + printf("header->name[5]:%x\n", header->name[5]); > + printf("header->name[6]:%x\n", header->name[6]); > + printf("header->name[7]:%x\n", header->name[7]); > + */ > +} > + > + > + > +static int am335x_i2c_write(i2c_bus *base, unsigned char chip, uint addr,int > alen, unsigned char *buffer, > + int len) > +{ > + > + bbb_i2c_bus *bus = (bbb_i2c_bus *) base; > + volatile bbb_i2c_regs *regs = bus->regs; > + > + int i; > + u16 status; > + int i2c_error = 0; > + int timeout = I2C_TIMEOUT; > + > + if (alen < 0) { > + puts("I2C write: addr len < 0\n"); > + return 1; > + } > + > + if (len < 0) { > + puts("I2C write: data len < 0\n"); > + return 1; > + } > + > + if (buffer == NULL) { > + puts("I2C write: NULL pointer passed\n"); > + return 1; > + } > + > + if (alen > 2) { > + printf("I2C write: addr len %d not supported\n", alen); > + return 1; > + } > + > + if (addr + len > (1 << 16)) { > + printf("I2C write: address 0x%x + 0x%x out of range\n", > + addr, len); > + return 1; > + } > + > + /* Wait until bus not busy */ > + if (wait_for_bb(&bus->base)) > + return 1; > + > + /* Start address phase - will write regoffset + len bytes data */ > + writew(alen + len, &bus->regs->BBB_I2C_CNT); > + /* Set slave address */ > + writew(chip,&bus->regs->BBB_I2C_SA); > + /* Stop bit needed here */ > + writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | > + I2C_CON_STP,&bus->regs->BBB_I2C_CON); > + > + while (alen) { > + /* Must write reg offset (one or two bytes) */ > + status = wait_for_event(&bus->base); > + /* Try to identify bus that is not padconf'd for I2C */ > + if (status == I2C_STAT_XRDY) { > + i2c_error = 2; > + printf("i2c_write: pads on bus probably not configured > (status=0x%x)\n",status); > + goto wr_exit; > + } > + if (status == 0 || (status & I2C_STAT_NACK)) { > + i2c_error = 1; > + printf("i2c_write: error waiting for addr ACK (status=0x%x)\n", > + status); > + goto wr_exit; > + } > + if (status & I2C_STAT_XRDY) { > + alen--; > + writeb((addr >> (8 * alen)) & 0xff, &bus->regs->BBB_I2C_DATA); > + writew(I2C_STAT_XRDY, &bus->regs->BBB_I2C_IRQSTATUS); > + } else { > + i2c_error = 1; > + printf("i2c_write: bus not ready for addr Tx (status=0x%x)\n", > + status); > + goto wr_exit; > + } > + } > + /* Address phase is over, now write data */ > + for (i = 0; i < len; i++) { > + status = wait_for_event(&bus->base); > + if (status == 0 || (status & I2C_STAT_NACK)) { > + i2c_error = 1; > + printf("i2c_write: error waiting for data ACK (status=0x%x)\n", > + status); > + goto wr_exit; > + } > + if (status & I2C_STAT_XRDY) { > + writeb(buffer[i], &bus->regs->BBB_I2C_DATA); > + writew(I2C_STAT_XRDY, &bus->regs->BBB_I2C_IRQSTATUS); > + } else { > + i2c_error = 1; > + printf("i2c_write: bus not ready for data Tx (i=%d)\n", > + i); > + goto wr_exit; > + } > + } > + /* > + * poll ARDY bit for making sure that last byte really has been > + * transferred on the bus. > + */ > + do { > + status = wait_for_event(&bus->base); > + } while (!(status & I2C_STAT_ARDY) && timeout--); > + if (timeout <= 0) > + printf("i2c_write: timed out writig last byte!\n"); > + > +wr_exit: > + flush_fifo(&bus->base); > + writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS); > + return i2c_error; > +} > + > + > diff --git a/c/src/lib/libbsp/arm/beagle/include/i2c.h > b/c/src/lib/libbsp/arm/beagle/include/i2c.h > index d4a9e32..6c924ee 100644 > --- a/c/src/lib/libbsp/arm/beagle/include/i2c.h > +++ b/c/src/lib/libbsp/arm/beagle/include/i2c.h > @@ -132,11 +132,11 @@ extern "C" { > > > #define DISP_LINE_LEN 128 > -#define I2C_TIMEOUT 1000 > +#define I2C_TIMEOUT 1001 > > #define I2C_BUS_MAX 3 > > -#define I2C_BASE1 (OMAP34XX_CORE_L4_IO_BASE + 0x070000) > +#define I2C_BASE1 (OMAP34XX_CORE_L4_IO_BASE + 0x070000) > //0x48000000+0x070000 > > #define I2C_DEFAULT_BASE I2C_BASE1 > > @@ -356,7 +356,7 @@ static inline rtems_status_code beagle_i2c_read( > | AM335X_I2C_IRQSTATUS_ARDY \ > | AM335X_I2C_IRQSTATUS_RRDY \ > | AM335X_I2C_IRQSTATUS_XRDY \ > - | AM335X_I2C_IRQSTATUS_XUDF) > + | AM335X_I2C_IRQSTATUS_XUDF ) > > #define BBB_I2C_IRQ_USED \ > ( BBB_I2C_IRQ_ERROR \ > @@ -478,6 +478,18 @@ static inline int bbb_register_i2c_2(void) > } > > > +struct am335x_baseboard_id { > + unsigned int magic; > + char name[8]; > + char version[4]; > + char serial[12]; > + char config[32]; > + char mac_addr[3][6]; > +}; > + > + > + > + > #ifdef __cplusplus > } > #endif /* __cplusplus */ > diff --git a/cpukit/dev/i2c/eeprom.c b/cpukit/dev/i2c/eeprom.c > index 39cff95..15040af 100644 > --- a/cpukit/dev/i2c/eeprom.c > +++ b/cpukit/dev/i2c/eeprom.c > @@ -55,6 +55,7 @@ static ssize_t eeprom_read( > off_t offset > ) > { > + > eeprom *dev = (eeprom *) base; > off_t avail = dev->size - offset; > uint32_t off = (uint32_t) offset; > @@ -86,6 +87,17 @@ static ssize_t eeprom_read( > (uint8_t) (off >> 16), > (uint8_t) (off >> 24) > }; > + > + i2c_msg msgs[1] = { > + { > + .addr = i2c_addr, > + .flags = I2C_M_RD, > + .buf = in, > + .len = cur > + } > + }; > + > + /* > i2c_msg msgs[2] = { > { > .addr = i2c_addr, > @@ -99,14 +111,22 @@ static ssize_t eeprom_read( > .len = cur > } > }; > + > + > + */ > int err; > + > + > > err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs)); > + > + > if (err != 0) { > return err; > } > - > + > todo -= cur; > + > off += cur; > in += cur; > } > @@ -236,7 +256,7 @@ int i2c_dev_register_eeprom( > } > > if (program_timeout_in_ms == 0) { > - program_timeout_in_ms = 1000; > + program_timeout_in_ms = 5000; > } > > dev = (eeprom *) > diff --git a/testsuites/samples/i2c0/init.c b/testsuites/samples/i2c0/init.c > index b428216..70bbe12 100644 > --- a/testsuites/samples/i2c0/init.c > +++ b/testsuites/samples/i2c0/init.c > @@ -23,10 +23,62 @@ > #include <rtems/score/assert.h> > #include <dev/i2c/eeprom.h> > > +#include <rtems/shell.h> > +#include <stdio.h> > +#include <stdarg.h> > +#include <stdlib.h> > +#include <string.h> > +#include <errno.h> > +#include <rtems/userenv.h> > + > +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER > +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER > +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER > +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER > +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK > + > +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM > + > +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 > + > +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 > + > +#define CONFIGURE_UNLIMITED_ALLOCATION_SIZE 32 > +#define CONFIGURE_UNLIMITED_OBJECTS > +#define CONFIGURE_UNIFIED_WORK_AREAS > + > +#define CONFIGURE_STACK_CHECKER_ENABLED > + > +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE > + > +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES > +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT > + > +#define CONFIGURE_INIT > + > +#include <rtems/confdefs.h> > + > + > +#define CONFIGURE_SHELL_COMMAND_CP > +#define CONFIGURE_SHELL_COMMAND_PWD > +#define CONFIGURE_SHELL_COMMAND_LS > +#define CONFIGURE_SHELL_COMMAND_LN > +#define CONFIGURE_SHELL_COMMAND_LSOF > +#define CONFIGURE_SHELL_COMMAND_CHDIR > +#define CONFIGURE_SHELL_COMMAND_CD > +#define CONFIGURE_SHELL_COMMAND_MKDIR > +#define CONFIGURE_SHELL_COMMAND_RMDIR > +#define CONFIGURE_SHELL_COMMAND_CAT > +#define CONFIGURE_SHELL_COMMAND_MV > +#define CONFIGURE_SHELL_COMMAND_RM > +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO > +#include <rtems/shellconfig.h> > + > + > /* I2C address of CAT24C256 eeprom > EEPROM SIZE 32 KB Ref: BBB SRM */ > #define I2C_SLAVE_ADDR (0x50) > -#define EEPROM_SIZE 256 > +#define EEPROM_SIZE 78 > #define EEPROM_PATH "/dev/i2c-0.eeprom" > > /* forward declarations to avoid warnings */ > @@ -35,16 +87,23 @@ rtems_task Init(rtems_task_argument argument); > const char rtems_test_name[] = "GSOC 2016 I2C TESTING"; > rtems_printer rtems_test_printer; > > + > rtems_task Init( > rtems_task_argument ignored > ) > { > + > rtems_test_begin(); > int i; > int rv,fd_bus,fd_in_dev; > uint8_t in[EEPROM_SIZE]; > struct stat st; > off_t off; > + ssize_t n; > + > + rtems_shell_env_t env; > + > + > > /*bus registration */ > rv = bbb_register_i2c_0(); > @@ -64,23 +123,56 @@ rtems_task Init( > 256, // size_in_bytes > 0 // program time out in ms > ); > + > + > + > + _Assert(rv == 0); > +// exit( 0 ); > printf("register EEPROM \n"); > fd_in_dev = open(EEPROM_PATH, O_RDWR); > + printf("fd_in_dev:%d\n", fd_in_dev); > _Assert(fd_in_dev >=0); > + > + > printf("open eeprom \n"); > rv = fstat(fd_in_dev, &st); > _Assert(rv == 0); > _Assert(st.st_blksize == 8); > _Assert(st.st_size == sizeof(in)); > > +printf("read func\n"); > + > + n = read(fd_in_dev, &in[0], sizeof(in)); > + printf("n:%d\n",n ); > + printf("0:%x, ",in[0]); > + printf("1:%x, ",in[1]); > + > + for(i=0;i<sizeof(in);++i) > + { > +printf("%x\n",in[i]); > + > + } > + > + > + > + printf("sizeof(in):%d\n", sizeof(in)); > + > + > + > + // _Assert(n == -1); > +/* > +printf("test\n"); > for ( i = 0; i < sizeof(in); ++i) { > + printf("i:%d\n",i); > off = lseek(fd_in_dev, 0, SEEK_SET); > + printf("lseek func done!\n"); > rv = read(fd_in_dev,&in[0], sizeof(in)); > - printf("\n %s \n ",in[i]); > + // printf("\n %s \n ",in[i]); > } > + */ > printf("EXIT from test case"); > close(fd_bus); > - unlink(BBB_I2C_2_BUS_PATH); > + unlink(BBB_I2C_2_BUS_PATH); > > rtems_test_end(); > } _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel