[PATCH] modify punitvara's works on BBB i2c, and now can read the eeprom info.

Sichen Zhao 1473996754 at qq.com
Tue Mar 14 14:05:36 UTC 2017


---
 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(&regs->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB)
+  unsigned short stat;
+  int timeout = I2C_TIMEOUT;
+
+  REG(&regs->BBB_I2C_IRQSTATUS)=0xffff;
+  printf("REG(&regs->BBB_I2C_IRQSTATUS_RAW):%x\n",REG(&regs->BBB_I2C_IRQSTATUS_RAW) );
+ // printf("%x\n",0x1400 & 0x1000 );
+ printf("REG(&regs->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB:%x\n",(REG(&regs->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB));
+while(stat =( REG(&regs->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB) && timeout--)
   {
-    status = true; 
-  } else {
-    status = false;
+
+REG(&regs->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(&regs->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(&regs->BBB_I2C_CON)=0x00;
   printk("inside BBB_I2C_CON value is %x \n",&regs->BBB_I2C_CON);
-  mmio_clear((&regs->BBB_I2C_CON),AM335X_I2C_CON_I2C_EN);
-  mmio_clear((&regs->BBB_I2C_SYSC),AM335X_I2C_SYSC_AUTOIDLE);  
+   REG(&regs->BBB_I2C_SYSC)= 0x2;
+//  mmio_clear((&regs->BBB_I2C_CON),AM335X_I2C_CON_I2C_EN);
+
+   REG(&regs->BBB_I2C_CON)= AM335X_I2C_CON_I2C_EN;
+
+   while((REG(&regs->BBB_I2C_SYSS) &I2C_SYSS_RDONE)==0)  //wait reset done
+   {
+    udelay(100);
+
+   }
+
+   REG(&regs->BBB_I2C_CON)=0x00;
+
+   am335x_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT);
+
+   REG(&regs->BBB_I2C_CON)= AM335X_I2C_CON_MST | AM335X_I2C_CON_I2C_EN;
+
+//  mmio_clear((&regs->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(&regs->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(&regs->BBB_I2C_CNT) = 0x02;
   no_bytes = REG(&regs->BBB_I2C_CNT);
 
+ // Set Slave address & Master enable, bring out of reset
+  REG(&regs->BBB_I2C_SA) = msgs->addr;
+  printf("slave address : %x\n",REG(&regs->BBB_I2C_SA));
+
+
   // I2C Controller in Master Mode
-  REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_START | AM335X_I2C_CON_MST;
+  REG(&regs->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(&regs->BBB_I2C_CON));
 
-  // Set Slave address & Master enable, bring out of reset
-  REG(&regs->BBB_I2C_SA) = msgs->addr;
-  printf("slave address : %x\n",REG(&regs->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(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;
+  REG(&regs->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(&regs->BBB_I2C_DATA));
+
+writeb(0x5,&regs->BBB_I2C_DATA);
+printf("(0x50 >> 8)& 0xff:%x\n",(0x50 >> 8)& 0xff);
+printf("REG(&regs->BBB_I2C_DATA):%x\n",readb(&regs->BBB_I2C_DATA) );
+printf("&regs->BBB_I2C_DATA:%x\n",&regs->BBB_I2C_DATA);
+//REG(&regs->BBB_I2C_IRQSTATUS)=AM335X_I2C_IRQSTATUS_XRDY;
+
+udelay(10);
+
+writeb(0x0,&regs->BBB_I2C_DATA);
+//REG(&regs->BBB_I2C_DATA)= ( (0x50 >> 0)& 0xff);
+printf("(0x50 >> 0)& 0xff:%x\n",(0x50 >> 0)& 0xff);
+printf("REG(&regs->BBB_I2C_DATA):%x\n",readb(&regs->BBB_I2C_DATA) );
+
+REG(&regs->BBB_I2C_IRQSTATUS)=AM335X_I2C_IRQSTATUS_XRDY;
+
+
+ // no_bytes = REG(&regs->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(&regs->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(&regs->BBB_I2C_DATA):%x\n",REG(&regs->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(&regs->BBB_I2C_DATA):%x\n",REG(&regs->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(&regs->BBB_I2C_IRQENABLE_SET) = BBB_I2C_IRQ_USED;
 
+ // REG(&regs->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(&regs->BBB_I2C_CON)=0;
+
   prescaler = (BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK) -1;
+  printf("prescaler:%d\n",prescaler );
   printk("PSC offset %x \n ",&regs->BBB_I2C_PSC);
   printk("PSC offset %x \n", &bus->regs->BBB_I2C_PSC);
   //mmio_write((&regs->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((&regs->BBB_I2C_SCLL), (divider - 7));
   REG(&bus->regs->BBB_I2C_SCLL) = (divider - 7);
   //mmio_write((&regs->BBB_I2C_SCLH), (divider - 5));
   printk("SCHL offset %x\n",&bus->regs->BBB_I2C_SCLH);
   REG(&bus->regs->BBB_I2C_SCLH) = (divider - 5);
+
+ REG(&regs->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(&regs->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();
 }
-- 
2.7.4





More information about the devel mailing list