<div>Hi Gedare Bloom,</div><div><br></div><div>Ok, i see, i will commit the code again.</div><div><br></div><div>Best Regards</div><div>Sichen Zhao</div><div><div><br></div><div style="font-size: 12px;font-family: Arial Narrow;padding:2px 0 2px 0;">------------------ Original ------------------</div><div style="font-size: 12px;background:#efefef;padding:8px;"><div><b>From: </b> "Gedare Bloom";<gedare@rtems.org>;</div><div><b>Date: </b> Thu, Mar 30, 2017 11:24 PM</div><div><b>To: </b> "Sichen Zhao"<1473996754@qq.com>; <wbr></div><div><b>Cc: </b> "devel@rtems.org"<devel@rtems.org>; <wbr></div><div><b>Subject: </b> Re: [PATCH 1/2] Beaglebone black i2c code, modify by Punit Vara - Addbeagle/bbb-i2c.c i2c driver - Modify include/i2c.h - Modify Makefile.am Buti2c cannot work currently</div></div><div><br></div>Hi Sichen,<br><br>Can you please make your git commit message a bit "cleaner" so that it<br>appears more nicely in git-log and in the email subject?<br>https://devel.rtems.org/wiki/Developer/Git#GitCommits Give a<br>descriptive short first line, followed by a blank line, and then the<br>more detailed commit message can follow.<br><br>Since this code was written by someone else, you should use the<br>--author="Punit Vara <...>" to give proper credit to him. This is part<br>of the reason to provide separate commits. Note that the author's name<br>is included in the git-commit information, so you don't need to also<br>repeat it in your commit message.<br><br>Thanks!<br>Gedare<br>On Wed, Mar 29, 2017 at 11:24 PM, Sichen Zhao <1473996754@qq.com> wrote:<br>> ---<br>>  c/src/lib/libbsp/arm/beagle/Makefile.am   |   4 +-<br>>  c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c | 788 ++++++++++++++++++++++++++++++<br>>  c/src/lib/libbsp/arm/beagle/include/i2c.h | 153 +++++-<br>>  3 files changed, 926 insertions(+), 19 deletions(-)<br>>  create mode 100644 c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c<br>><br>> diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am b/c/src/lib/libbsp/arm/beagle/Makefile.am<br>> index 8bb8478..4da72bc 100644<br>> --- a/c/src/lib/libbsp/arm/beagle/Makefile.am<br>> +++ b/c/src/lib/libbsp/arm/beagle/Makefile.am<br>> @@ -88,7 +88,6 @@ libbsp_a_SOURCES += ../../shared/timerstub.c<br>>  libbsp_a_SOURCES += ../../shared/cpucounterread.c<br>>  libbsp_a_SOURCES += ../shared/startup/bsp-start-memcpy.S<br>>  libbsp_a_SOURCES += ../shared/arm-cp15-set-exception-handler.c<br>> -libbsp_a_SOURCES += ../shared/arm-cp15-set-ttb-entries.c<br>><br>>  # Startup<br>>  libbsp_a_SOURCES += startup/bspreset.c<br>> @@ -116,6 +115,9 @@ libbsp_a_SOURCES += ../../shared/console.c \<br>>  # I2C<br>>  libbsp_a_SOURCES += misc/i2c.c<br>><br>> +# i2c<br>> +libbsp_a_SOURCES += i2c/bbb-i2c.c<br>> +<br>>  # GPIO<br>>  libbsp_a_SOURCES += gpio/bbb-gpio.c<br>><br>> diff --git a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c<br>> new file mode 100644<br>> index 0000000..cd1e9c1<br>> --- /dev/null<br>> +++ b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c<br>> @@ -0,0 +1,788 @@<br>> +/**<br>> + * @file<br>> + *<br>> + * @ingroup arm_beagle<br>> + *<br>> + * @brief BeagleBoard I2C bus initialization and API Support.<br>> + */<br>> +<br>> +/*<br>> + * Copyright (c) 2016 Punit Vara <punitvara at gmail.com><br>> + *<br>> + * The license and distribution terms for this file may be<br>> + * found in the file LICENSE in this distribution or at<br>> + * http://www.rtems.org/license/LICENSE.<br>> + */<br>> +<br>> +#include <stdio.h><br>> +#include <bsp/i2c.h><br>> +#include <libcpu/am335x.h><br>> +#include <rtems/irq-extension.h><br>> +#include <bsp/bbb-gpio.h><br>> +#include <rtems/score/assert.h><br>> +<br>> +/*<br>> +static bool am335x_i2c_pinmux(bbb_i2c_bus *bus)<br>> +{<br>> +  bool status =true;<br>> +    // We will check i2c_bus_id in am335x_i2c_bus_register<br>> +    // Apart from mode and pull_up register what about SCREWCTRL & RXACTIVE ??<br>> +  if (bus->i2c_bus_id == I2C1) {<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_CS0) = (BBB_MUXMODE(MODE2) | BBB_PU_EN);<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D1) = (BBB_MUXMODE(MODE2) | BBB_PU_EN);<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_TXD) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RXD) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> +  } else if (bus->i2c_bus_id == I2C2) {<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RTSN) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_CTSN) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> +    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> +  } else {<br>> +  status = false;<br>> +  }<br>> +  return status;<br>> +}<br>> +*/<br>> +<br>> +/* ref. Table 21-4 I2C Clock Signals */<br>> +/*<br>> + For I2C1/2<br>> + Interface clock - 100MHz - CORE_LKOUTM4 / 2 - pd_per_l4ls_gclk<br>> + Functional clock - 48MHz - PER_CLKOUTM2 / 4 - pd_per_ic2_fclk<br>> +*/<br>> +<br>> +/*<br>> +static void am335x_i2c1_i2c2_module_clk_config(bbb_i2c_bus *bus)<br>> +{<br>> +*/<br>> +/*0x2 = SW_WKUP : SW_WKUP: Start a software forced wake-up<br>> +transition on the domain. */<br>> +/*<br>> +  REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) |=<br>> +                        AM335X_CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> +  while((REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) &<br>> +                        AM335X_CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL) !=<br>> +                        AM335X_CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP);<br>> +*/<br>> +<br>> +/* 0x2 = ENABLE : Module is explicitly enabled. Interface clock (if not<br>> +used for functions) may be gated according to the clock domain<br>> +state. Functional clocks are guarantied to stay present. As long as in<br>> +this configuration, power domain sleep transition cannot happen.*/<br>> + /* REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKCTRL) |=<br>> +                        AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE;<br>> +  while((REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKCTRL) &<br>> +      AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE) != AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE);<br>> +*/<br>> +/*0x2 = ENABLE : Module is explicitly enabled. Interface clock (if not<br>> +used for functions) may be gated according to the clock domain<br>> +state. Functional clocks are guarantied to stay present. As long as in<br>> +this configuration, power domain sleep transition cannot happen.*/<br>> +/*<br>> +  if (bus->i2c_bus_id == I2C1) {<br>> +  REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C1_CLKCTRL) |=<br>> +                             AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE;<br>> +  while(REG((AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C1_CLKCTRL) &<br>> +     AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE) != AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE);<br>> +  } else if (bus->i2c_bus_id == I2C2) {<br>> +  REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C2_CLKCTRL) |=<br>> +                             AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE;<br>> +  while(REG((AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C2_CLKCTRL) &<br>> +     AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE) != AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE);<br>> +  while(!(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) &<br>> +           (AM335X_CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |<br>> +            AM335X_CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_I2C_FCLK)));<br>> +  }<br>> +}<br>> +*/<br>> +<br>> +static void am335x_i2c0_pinmux(bbb_i2c_bus *bus)<br>> +{<br>> +  REG(bus->regs + AM335X_CONF_I2C0_SDA) =<br>> +  (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN);<br>> +<br>> +  REG(bus->regs + AM335X_CONF_I2C0_SCL) =<br>> +  (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN);<br>> +}<br>> +<br>> +static void I2C0ModuleClkConfig(void)<br>> +{<br>> +    /* Configuring L3 Interface Clocks. */<br>> +<br>> +    /* Writing to MODULEMODE field of CM_PER_L3_CLKCTRL register. */<br>> +    REG(AM335X_CM_PER_ADDR + CM_PER_L3_CLKCTRL) |=<br>> +          CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE;<br>> +<br>> +    /* Waiting for MODULEMODE field to reflect the written value. */<br>> +    while(CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3_CLKCTRL) &<br>> +           CM_PER_L3_CLKCTRL_MODULEMODE));<br>> +<br>> +    /* Writing to MODULEMODE field of CM_PER_L3_INSTR_CLKCTRL register. */<br>> +    REG(AM335X_CM_PER_ADDR + CM_PER_L3_INSTR_CLKCTRL) |=<br>> +          CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE;<br>> +<br>> +    /* Waiting for MODULEMODE field to reflect the written value. */<br>> +    while(CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3_INSTR_CLKCTRL) &<br>> +           CM_PER_L3_INSTR_CLKCTRL_MODULEMODE));<br>> +<br>> +    /* Writing to CLKTRCTRL field of CM_PER_L3_CLKSTCTRL register. */<br>> +    REG(AM335X_CM_PER_ADDR + CM_PER_L3_CLKSTCTRL) |=<br>> +          CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> +<br>> +    /* Waiting for CLKTRCTRL field to reflect the written value. */<br>> +    while(CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3_CLKSTCTRL) &<br>> +           CM_PER_L3_CLKSTCTRL_CLKTRCTRL));<br>> +<br>> +    /* Writing to CLKTRCTRL field of CM_PER_OCPWP_L3_CLKSTCTRL register. */<br>> +    REG(AM335X_CM_PER_ADDR + CM_PER_OCPWP_L3_CLKSTCTRL) |=<br>> +          CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> +<br>> +    /*Waiting for CLKTRCTRL field to reflect the written value. */<br>> +    while(CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_OCPWP_L3_CLKSTCTRL) &<br>> +           CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL));<br>> +<br>> +    /* Writing to CLKTRCTRL field of CM_PER_L3S_CLKSTCTRL register. */<br>> +    REG(AM335X_CM_PER_ADDR + CM_PER_L3S_CLKSTCTRL) |=<br>> +          CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> +<br>> +    /*Waiting for CLKTRCTRL field to reflect the written value. */<br>> +    while(CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3S_CLKSTCTRL) &<br>> +           CM_PER_L3S_CLKSTCTRL_CLKTRCTRL));<br>> +<br>> +    /* Checking fields for necessary values.  */<br>> +<br>> +    /* Waiting for IDLEST field in CM_PER_L3_CLKCTRL register to be set to 0x0. */<br>> +    while((CM_PER_L3_CLKCTRL_IDLEST_FUNC << CM_PER_L3_CLKCTRL_IDLEST_SHIFT)!=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3_CLKCTRL) &<br>> +           CM_PER_L3_CLKCTRL_IDLEST));<br>> +<br>> +    /*<br>> +    ** Waiting for IDLEST field in CM_PER_L3_INSTR_CLKCTRL register to attain the<br>> +    ** desired value.<br>> +    */<br>> +    while((CM_PER_L3_INSTR_CLKCTRL_IDLEST_FUNC <<<br>> +           CM_PER_L3_INSTR_CLKCTRL_IDLEST_SHIFT)!=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3_INSTR_CLKCTRL) &<br>> +           CM_PER_L3_INSTR_CLKCTRL_IDLEST));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_L3_GCLK field in CM_PER_L3_CLKSTCTRL register to<br>> +    ** attain the desired value.<br>> +    */<br>> +    while(CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3_CLKSTCTRL) &<br>> +           CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_OCPWP_L3_GCLK field in CM_PER_OCPWP_L3_CLKSTCTRL<br>> +    ** register to attain the desired value.<br>> +    */<br>> +    while(CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_OCPWP_L3_CLKSTCTRL) &<br>> +           CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_L3S_GCLK field in CM_PER_L3S_CLKSTCTRL register<br>> +    ** to attain the desired value.<br>> +    */<br>> +    while(CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK !=<br>> +          (REG(AM335X_CM_PER_ADDR + CM_PER_L3S_CLKSTCTRL) &<br>> +          CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK));<br>> +<br>> +<br>> +    /* Configuring registers related to Wake-Up region. */<br>> +<br>> +    /* Writing to MODULEMODE field of CM_WKUP_CONTROL_CLKCTRL register. */<br>> +    REG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) |=<br>> +          CM_WKUP_CONTROL_CLKCTRL_MODULEMODE_ENABLE;<br>> +<br>> +    /* Waiting for MODULEMODE field to reflect the written value. */<br>> +    while(CM_WKUP_CONTROL_CLKCTRL_MODULEMODE_ENABLE !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) &<br>> +           CM_WKUP_CONTROL_CLKCTRL_MODULEMODE));<br>> +<br>> +    /* Writing to CLKTRCTRL field of CM_PER_L3S_CLKSTCTRL register. */<br>> +    REG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) |=<br>> +          CM_WKUP_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> +<br>> +    /*Waiting for CLKTRCTRL field to reflect the written value. */<br>> +    while(CM_WKUP_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) &<br>> +           CM_WKUP_CLKSTCTRL_CLKTRCTRL));<br>> +<br>> +    /* Writing to CLKTRCTRL field of CM_L3_AON_CLKSTCTRL register. */<br>> +    REG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L3_AON_CLKSTCTRL) |=<br>> +          CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> +<br>> +    /*Waiting for CLKTRCTRL field to reflect the written value. */<br>> +    while(CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKTRCTRL_SW_WKUP !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L3_AON_CLKSTCTRL) &<br>> +           CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKTRCTRL));<br>> +<br>> +    /* Writing to MODULEMODE field of CM_WKUP_I2C0_CLKCTRL register. */<br>> +    REG(SOC_CM_WKUP_REGS + CM_WKUP_I2C0_CLKCTRL) |=<br>> +          CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE;<br>> +<br>> +    /* Waiting for MODULEMODE field to reflect the written value. */<br>> +    while(CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_I2C0_CLKCTRL) &<br>> +           CM_WKUP_I2C0_CLKCTRL_MODULEMODE));<br>> +<br>> +    /* Verifying if the other bits are set to required settings. */<br>> +<br>> +    /*<br>> +    ** Waiting for IDLEST field in CM_WKUP_CONTROL_CLKCTRL register to attain<br>> +    ** desired value.<br>> +    */<br>> +    while((CM_WKUP_CONTROL_CLKCTRL_IDLEST_FUNC <<<br>> +           CM_WKUP_CONTROL_CLKCTRL_IDLEST_SHIFT) !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) &<br>> +           CM_WKUP_CONTROL_CLKCTRL_IDLEST));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_L3_AON_GCLK field in CM_L3_AON_CLKSTCTRL<br>> +    ** register to attain desired value.<br>> +    */<br>> +    while(CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKACTIVITY_L3_AON_GCLK !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L3_AON_CLKSTCTRL) &<br>> +           CM_WKUP_CM_L3_AON_CLKSTCTRL_CLKACTIVITY_L3_AON_GCLK));<br>> +<br>> +    /*<br>> +    ** Waiting for IDLEST field in CM_WKUP_L4WKUP_CLKCTRL register to attain<br>> +    ** desired value.<br>> +    */<br>> +    while((CM_WKUP_L4WKUP_CLKCTRL_IDLEST_FUNC <<<br>> +           CM_WKUP_L4WKUP_CLKCTRL_IDLEST_SHIFT) !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_L4WKUP_CLKCTRL) &<br>> +           CM_WKUP_L4WKUP_CLKCTRL_IDLEST));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_L4_WKUP_GCLK field in CM_WKUP_CLKSTCTRL register<br>> +    ** to attain desired value.<br>> +    */<br>> +    while(CM_WKUP_CLKSTCTRL_CLKACTIVITY_L4_WKUP_GCLK !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) &<br>> +           CM_WKUP_CLKSTCTRL_CLKACTIVITY_L4_WKUP_GCLK));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_L4_WKUP_AON_GCLK field in CM_L4_WKUP_AON_CLKSTCTRL<br>> +    ** register to attain desired value.<br>> +    */<br>> +    while(CM_WKUP_CM_L4_WKUP_AON_CLKSTCTRL_CLKACTIVITY_L4_WKUP_AON_GCLK !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CM_L4_WKUP_AON_CLKSTCTRL) &<br>> +           CM_WKUP_CM_L4_WKUP_AON_CLKSTCTRL_CLKACTIVITY_L4_WKUP_AON_GCLK));<br>> +<br>> +    /*<br>> +    ** Waiting for CLKACTIVITY_I2C0_GFCLK field in CM_WKUP_CLKSTCTRL<br>> +    ** register to attain desired value.<br>> +    */<br>> +    while(CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_CLKSTCTRL) &<br>> +           CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK));<br>> +<br>> +    /*<br>> +    ** Waiting for IDLEST field in CM_WKUP_I2C0_CLKCTRL register to attain<br>> +    ** desired value.<br>> +    */<br>> +    while((CM_WKUP_I2C0_CLKCTRL_IDLEST_FUNC <<<br>> +           CM_WKUP_I2C0_CLKCTRL_IDLEST_SHIFT) !=<br>> +          (REG(SOC_CM_WKUP_REGS + CM_WKUP_I2C0_CLKCTRL) &<br>> +           CM_WKUP_I2C0_CLKCTRL_IDLEST));<br>> +}<br>> +<br>> +/*<br>> +void am335x_i2c_init(bbb_i2c_bus *bus, uint32_t input_clock)<br>> +{<br>> +  // am335x_i2c_pinmux()<br>> +  // am335x_i2c1_i2c2_module_clk_config<br>> +}<br>> +*/<br>> +<br>> +static bool am335x_i2c_busbusy(volatile bbb_i2c_regs *regs)<br>> +{<br>> +  bool status;<br>> +<br>> +  if (REG(&regs->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB)<br>> +  {<br>> +    status = true;<br>> +  } else {<br>> +    status = false;<br>> +  }<br>> +  return status;<br>> +}<br>> +<br>> +static void am335x_i2c_reset(bbb_i2c_bus *bus)<br>> +{<br>> +  volatile bbb_i2c_regs *regs = bus->regs;<br>> +  printk("reset bus->reg is %x \n",bus->regs);<br>> +  /* Disable I2C module at the time of initialization*/<br>> +  /*Should I use write32 ?? I guess mmio_clear is correct choice here*/<br>> +  printk("inside BBB_I2C_CON value is %x \n",&regs->BBB_I2C_CON);<br>> +  mmio_clear((&regs->BBB_I2C_CON),AM335X_I2C_CON_I2C_EN);<br>> +  mmio_clear((&regs->BBB_I2C_SYSC),AM335X_I2C_SYSC_AUTOIDLE);<br>> +  //REG(bus->regs + AM335X_I2C_CON) &= ~(AM335X_I2C_CON_I2C_EN);<br>> +  //REG(bus->regs + AM335X_I2C_SYSC) &= ~(AM335X_I2C_SYSC_AUTOIDLE);<br>> +<br>> +  /*<br>> +  can I clear all the interrupt here ?<br>> +  mmio_write(get_reg_addr(bbb_i2c_bus->reg->AM335X_I2C_IRQ_ENABLE_CLR), ??)<br>> +  */<br>> +}<br>> +<br>> +/*<br>> +Possible values for msg->flag<br>> +   * - @ref I2C_M_TEN,<br>> +   * - @ref I2C_M_RD,<br>> +   * - @ref I2C_M_STOP,<br>> +   * - @ref I2C_M_NOSTART,<br>> +   * - @ref I2C_M_REV_DIR_ADDR,<br>> +   * - @ref I2C_M_IGNORE_NAK,<br>> +   * - @ref I2C_M_NO_RD_ACK, and<br>> +   * - @ref I2C_M_RECV_LEN.<br>> +*/<br>> +<br>> +static void am335x_i2c_set_address_size(const i2c_msg *msgs,volatile bbb_i2c_regs *regs)<br>> +{<br>> +    /*can be configured multiple modes here. Need to think about own address modes*/<br>> +  if ((msgs->flags & I2C_M_TEN) == 0)  {/* 7-bit mode slave address mode*/<br>> +  mmio_write(&regs->BBB_I2C_CON,(AM335X_I2C_CFG_7BIT_SLAVE_ADDR | AM335X_I2C_CON_I2C_EN));<br>> +  } else { /* 10-bit slave address mode*/<br>> +  mmio_write(&regs->BBB_I2C_CON,(AM335X_I2C_CFG_10BIT_SLAVE_ADDR | AM335X_I2C_CON_I2C_EN));<br>> +  }<br>> +  }<br>> +<br>> +static void am335x_i2c_next_byte(bbb_i2c_bus *bus)<br>> +{<br>> +  i2c_msg *msg;<br>> +<br>> +  printk("Enter next_byte\n");<br>> +  ++bus->msgs;<br>> +  --bus->msg_todo;<br>> +<br>> +  msg = &bus->msgs[0];<br>> +<br>> +  bus->current_msg_todo = msg->len;<br>> +  bus->current_msg_byte = msg->buf;<br>> +}<br>> +<br>> +static unsigned int am335x_i2c_intrawstatus(volatile bbb_i2c_regs *regs)<br>> +{<br>> +  return (REG(&regs->BBB_I2C_IRQSTATUS_RAW));<br>> +}<br>> +<br>> +static void am335x_i2c_masterint_enable(volatile bbb_i2c_regs *regs, unsigned int flag)<br>> +{<br>> +  REG(&regs->BBB_I2C_IRQENABLE_SET) |= flag;<br>> +}<br>> +<br>> +static void am335x_i2c_masterint_disable(volatile bbb_i2c_regs *regs, unsigned int flag)<br>> +{<br>> + REG(&regs->BBB_I2C_IRQENABLE_CLR) = flag;<br>> +}<br>> +<br>> +static void am335x_int_clear(volatile bbb_i2c_regs *regs, unsigned int flag)<br>> +{<br>> +  REG(&regs->BBB_I2C_IRQSTATUS) = flag;<br>> +}<br>> +<br>> +<br>> +static void am335x_clean_interrupts(volatile bbb_i2c_regs *regs)<br>> +{<br>> +  am335x_i2c_masterint_enable(regs,0x7FFF);<br>> +  am335x_int_clear(regs,0x7FFF);<br>> +  am335x_i2c_masterint_disable(regs,0x7FFF);<br>> +}<br>> +<br>> +<br>> +static void am335x_i2c_setup_read_transfer(bbb_i2c_bus *bus, volatile bbb_i2c_regs *regs, const i2c_msg *msgs, bool send_stop)<br>> +{<br>> +  volatile unsigned int no_bytes;<br>> +  //am335x_i2c_masterint_enable(regs, AM335X_I2C_INT_RECV_READY);<br>> +   // No of data to be transmitted at a time<br>> +  REG(&regs->BBB_I2C_CNT) = 0x02;<br>> +  no_bytes = REG(&regs->BBB_I2C_CNT);<br>> +<br>> +  // I2C Controller in Master Mode<br>> +  REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_START | AM335X_I2C_CON_MST;<br>> +  printk("set master in transmission mode %x \n",REG(&regs->BBB_I2C_CON));<br>> +<br>> +  // Set Slave address & Master enable, bring out of reset<br>> +  REG(&regs->BBB_I2C_SA) = msgs->addr;<br>> +  printf("slave address : %x\n",REG(&regs->BBB_I2C_SA));<br>> +<br>> +  // clear status of all interrupts<br>> +  am335x_clean_interrupts(regs);<br>> +  printk("\n set memory address to read\n");<br>> +<br>> +  // transmit interrupt is enabled<br>> +  am335x_i2c_masterint_enable(regs,AM335X_I2C_IRQSTATUS_XRDY);<br>> +  printk("Enable transmit interrupt \n");<br>> +  //start condition<br>> +  REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;<br>> +  printk("start transmission \n");<br>> +  while(am335x_i2c_busbusy(regs) == 0);<br>> +  printk("bus is free \n");<br>> +  printk("CNT : %x\n", no_bytes);<br>> +  while(0 != no_bytes);<br>> +  printk("total msg count for tranmission is zero \n");<br>> +  while( !(am335x_i2c_intrawstatus(regs) & (AM335X_I2C_IRQSTATUS_ARDY)));<br>> +<br>> +  printk("Enter read transfer \n");<br>> +   // No of data to be received at a time(msg_count!!)<br>> +  printk("msg_todo for read is %d \n",bus->msg_todo);<br>> +  REG(&regs->BBB_I2C_CNT) = bus->msg_todo;<br>> +<br>> +  // clear status of all interrupts<br>> +  //am335x_clean_interrupts(regs);<br>> +<br>> +  // I2C Controller in Master Mode<br>> +  REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_RX | AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_MST;<br>> +  printk("Set master to receiver mode %x \n", REG(&regs->BBB_I2C_CON));<br>> +  // receive interrupt is enabled<br>> +  am335x_i2c_masterint_enable(regs, AM335X_I2C_INT_RECV_READY | AM335X_I2C_INT_STOP_CONDITION);<br>> +<br>> +  if (send_stop) {<br>> +    // stop condition<br>> +    printk("stop to read\n");<br>> +    REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> +  } else {<br>> +    // start condition<br>> +    printk("start to read\n");<br>> +    REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;<br>> +  }<br>> +  while(am335x_i2c_busbusy(regs) == 0);<br>> +  printk("Exit read transfer\n");<br>> +}<br>> +<br>> +<br>> +static void am335x_i2c_continue_read_transfer(<br>> +  bbb_i2c_bus *bus,<br>> +  volatile bbb_i2c_regs *regs<br>> +)<br>> +{<br>> +  printk("enter continue read transfer \n");<br>> +  bus->current_msg_byte[bus->already_transferred] = REG(&regs->BBB_I2C_DATA);<br>> +  bus->already_transferred++;<br>> +  am335x_int_clear(regs,AM335X_I2C_INT_RECV_READY);<br>> +  printk("clear RRDY in continue read transfer\n");<br>> +<br>> +  if (bus->already_transferred == REG(&regs->BBB_I2C_CNT)) {<br>> +    printk("continue read transfer finished \n");<br>> +    //am335x_i2c_setup_read_transfer(bus,regs,false);<br>> +    am335x_i2c_masterint_disable(regs, AM335X_I2C_INT_RECV_READY);<br>> +    printk("disable RRDY in continue read transfer\n");<br>> +    REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> +    printk("stop condition in continue read transfer %x\n",REG(&regs->BBB_I2C_CON));<br>> +  }<br>> +}<br>> +<br>> +static void am335x_i2c_continue_write(bbb_i2c_bus *bus, volatile bbb_i2c_regs *regs)<br>> +{<br>> +   REG(&regs->BBB_I2C_DATA) = 0x00;<br>> +   am335x_int_clear(regs, AM335X_I2C_IRQSTATUS_XRDY);<br>> +   printk("clear XRDY continue write\n");<br>> +   /*<br>> +   if (bus->already_transferred == REG(&regs->BBB_I2C_CNT)) {<br>> +   printk("\n finished transfer \n");<br>> +   am335x_i2c_masterint_disable(regs, AM335X_I2C_IRQSTATUS_XRDY);<br>> +   printk("disable XRDY continue write \n");<br>> +   REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> +   } else {<br>> +     printk("write memory address \n");<br>> +     REG(&regs->BBB_I2C_DATA) = *bus->current_msg_byte;<br>> +  }<br>> +   */<br>> +<br>> +  /*<br>> +   if (bus->already_transferred == bus->msg_todo) {<br>> +     printk("finished transfer \n");<br>> +     am335x_int_clear(regs, AM335X_I2C_IRQSTATUS_XRDY);<br>> +     REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> +   } else {<br>> +     printk("remaining byte \n");<br>> +     REG(&regs->BBB_I2C_DATA) = bus->current_msg_byte[bus->already_transferred];<br>> +     printk("%s",REG(&regs->BBB_I2C_DATA));<br>> +     bus->already_transferred++;<br>> +   }<br>> +   */<br>> +}<br>> +<br>> +static void am335x_i2c_setup_write_transfer(bbb_i2c_bus *bus,volatile bbb_i2c_regs *regs)<br>> +{<br>> +  volatile unsigned int no_bytes;<br>> +  printk(" \n Enter write transfer \n");<br>> +<br>> +  // Following data count specify bytes to be transmitted<br>> +  REG(&regs->BBB_I2C_CNT) = bus->msg_todo;<br>> +  no_bytes = REG(&regs->BBB_I2C_CNT);<br>> +  // clear status of all interrupts<br>> +  // Already cleaned during reset<br>> +  am335x_clean_interrupts(regs);<br>> +<br>> +  // I2C Controller in Master transmitter Mode<br>> +  REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN;<br>> +  printk("enable master in transmiter mode setup write %x\n",REG(&regs->BBB_I2C_CON));<br>> +<br>> +  // transmit interrupt is enabled<br>> +  am335x_i2c_masterint_enable(regs,AM335X_I2C_IRQSTATUS_XRDY);<br>> +  printk("enable XRDY setup write\n");<br>> +<br>> +  //start condition<br>> +  REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;<br>> +  printk("set start condition in setup write %x \n",REG(&regs->BBB_I2C_CON));<br>> +<br>> +  while(am335x_i2c_busbusy(regs) == 0);<br>> +  printk("CNT in setup write : %x \n",REG(&regs->BBB_I2C_CNT));<br>> +  printk("setup write msg_todo %x \n",bus->current_todo);<br>> +  while(0 != no_bytes);<br>> +  printk("check whether ???\n");<br>> +  printk("RAW =  %x",REG(&regs->BBB_I2C_IRQSTATUS_RAW));<br>> +  while( !((am335x_i2c_intrawstatus(regs)) & (AM335X_I2C_IRQSTATUS_ARDY)));<br>> +  printk("exit setup write \n");<br>> +}<br>> +<br>> +<br>> +static void am335x_i2c_setup_transfer(bbb_i2c_bus *bus, volatile bbb_i2c_regs *regs)<br>> +{<br>> +  const i2c_msg *msgs = bus->msgs;<br>> +  uint32_t msg_todo = bus->msg_todo;<br>> +  bool send_stop = false;<br>> +  uint32_t i;<br>> +<br>> +  printk("Enter setup transfer\n");<br>> +  bus->current_todo = msgs[0].len;<br>> +<br>> +  for (i = 1; i < msg_todo && (msgs[i].flags & I2C_M_NOSTART) != 0; ++i) {<br>> +    bus->current_todo += msgs[i].len;<br>> +  }<br>> +<br>> +  regs = bus->regs;<br>> +<br>> +  REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_TXFIFO_CLR;<br>> +  REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_RXFIFO_CLR;<br>> +  am335x_i2c_set_address_size(msgs,regs);<br>> +  bus->read = ((bus->read == true) ? 0:1);<br>> +  bus->already_transferred = (bus->read == true) ? 0 : 1;<br>> +<br>> +  if (bus->read) {<br>> +    if (REG(&regs->BBB_I2C_CNT) == 1) {<br>> +      send_stop = true;<br>> +    }<br>> +    printk("configure to read bus\n");<br>> +    am335x_i2c_setup_read_transfer(bus,regs,msgs,send_stop);<br>> +  } else {<br>> +    printk("configure to write bus\n");<br>> +    am335x_i2c_setup_write_transfer(bus,regs);<br>> +  }<br>> +<br>> +}<br>> +<br>> +static void am335x_i2c_interrupt(void *arg)<br>> +{<br>> +  bbb_i2c_bus *bus = arg;<br>> +  volatile bbb_i2c_regs *regs = bus->regs;<br>> +  /* get status of enabled interrupts */<br>> +  uint32_t irqstatus = REG(&regs->BBB_I2C_IRQSTATUS);<br>> +  bool done = false;<br>> +  printk("\n inside interrupt function \n");<br>> +  /* Clear all enabled interrupt except receive ready and transmit ready interrupt in status register */<br>> +  REG(&regs->BBB_I2C_IRQSTATUS) = (irqstatus & ~(AM335X_I2C_IRQSTATUS_RRDY | AM335X_I2C_IRQSTATUS_XRDY));<br>> +  printk("\n irqstatus = %x \n",REG(&regs->BBB_I2C_IRQSTATUS));<br>> +<br>> +  if (irqstatus & AM335X_I2C_INT_RECV_READY) {<br>> +     printk("\nInside receive interrupt\n");<br>> +    am335x_i2c_continue_read_transfer(bus, regs);<br>> +  }<br>> +<br>> +  if (irqstatus & AM335X_I2C_IRQSTATUS_XRDY) {<br>> +    printk("\ninside transmit interrupt \n");<br>> +    am335x_i2c_continue_write(bus,regs);<br>> +  }<br>> +<br>> +  if (irqstatus & AM335X_I2C_IRQSTATUS_NACK) {<br>> +    done = true;<br>> +    printk("inside NACK\n");<br>> +    am335x_i2c_masterint_disable(regs,AM335X_I2C_IRQSTATUS_NACK);<br>> +  }<br>> +<br>> +  if (irqstatus & AM335X_I2C_IRQSTATUS_BF) {<br>> +    done = true;<br>> +    printk("inside BF \n ");<br>> +  }<br>> +<br>> +  if (done) {<br>> +    uint32_t err = irqstatus & BBB_I2C_IRQ_ERROR;<br>> +    printk("interrupt done \n");<br>> +<br>> +    am335x_i2c_next_byte(bus);<br>> +<br>> +    if (bus->msg_todo == 0 || err != 0) {<br>> +    rtems_status_code sc;<br>> +<br>> +    // am335x_i2c_disable_interrupts(regs);<br>> +    am335x_i2c_masterint_disable(regs, (AM335X_I2C_IRQSTATUS_RRDY | AM335X_I2C_IRQSTATUS_XRDY | AM335X_I2C_IRQSTATUS_BF));<br>> +<br>> +    REG(&regs->BBB_I2C_IRQSTATUS) = err;<br>> +<br>> +    sc = rtems_event_transient_send(bus->task_id);<br>> +    _Assert(sc == RTEMS_SUCCESSFUL);<br>> +    (void) sc;<br>> +    } else {<br>> +      am335x_i2c_setup_transfer(bus, regs);<br>> +    }<br>> +  }<br>> +}<br>> +<br>> +static int am335x_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)<br>> +{<br>> +  rtems_status_code sc;<br>> +  bbb_i2c_bus *bus = (bbb_i2c_bus *)base;<br>> +  volatile bbb_i2c_regs *regs;<br>> +  uint32_t i;<br>> + printk("\n enter transfer ");<br>> +  rtems_task_wake_after(1);<br>> +<br>> +<br>> +  if (msg_count < 1){<br>> +    return 1;<br>> +  }<br>> +<br>> +  for (i=0; i<msg_count;++i) {<br>> +      if ((msgs[i].flags & I2C_M_RECV_LEN) != 0) {<br>> +        return -EINVAL;<br>> +      }<br>> +  }<br>> +<br>> +  bus->msgs = &msgs[0];<br>> +  bus->msg_todo = msg_count;<br>> +  printk("total msg = msg_count : %x \n",bus->msg_todo);<br>> +  bus->current_msg_todo = msgs[0].len;// current data size<br>> +  bus->current_msg_byte = msgs[0].buf;// current data<br>> +  printk("\n current_msg_todo %x \n ",msgs[0].len);<br>> +  printk("\n current_msg_byte %x \n ",msgs[0].buf);<br>> +  bus->task_id = rtems_task_self();<br>> +<br>> +  regs = bus->regs;<br>> +  am335x_i2c_setup_transfer(bus,regs);<br>> +  REG(&regs->BBB_I2C_IRQENABLE_SET) = BBB_I2C_IRQ_USED;<br>> +<br>> +  sc = rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout);<br>> +  // If timeout then return timeout error<br>> +  if (sc != RTEMS_SUCCESSFUL) {<br>> +    am335x_i2c_reset(bus);<br>> +<br>> +    rtems_event_transient_clear();<br>> +<br>> +    return -ETIMEDOUT;<br>> +  }<br>> +  printk("exit transfer\n");<br>> +  // return bus->regs->BBB_I2C_IRQSTATUS == 0 ? 0 : -EIO;<br>> +  return 0;<br>> +}<br>> +<br>> +static int am335x_i2c_set_clock(i2c_bus *base, unsigned long clock)<br>> +{<br>> +  bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>> +  volatile bbb_i2c_regs *regs = bus->regs;<br>> +  uint32_t prescaler,divider;<br>> +<br>> +  printk("set clock start\n");<br>> +  prescaler = (BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK) -1;<br>> +  printk("PSC offset %x \n ",&regs->BBB_I2C_PSC);<br>> +  printk("PSC offset %x \n", &bus->regs->BBB_I2C_PSC);<br>> +  //mmio_write((&regs->BBB_I2C_PSC), prescaler);<br>> +  REG(&bus->regs->BBB_I2C_PSC) = prescaler;<br>> +<br>> +  divider = BBB_I2C_INTERNAL_CLK/(2*clock);<br>> +  printk("SCLL offset %x \n",&bus->regs->BBB_I2C_SCLL);<br>> +  //mmio_write((&regs->BBB_I2C_SCLL), (divider - 7));<br>> +  REG(&bus->regs->BBB_I2C_SCLL) = (divider - 7);<br>> +  //mmio_write((&regs->BBB_I2C_SCLH), (divider - 5));<br>> +  printk("SCHL offset %x\n",&bus->regs->BBB_I2C_SCLH);<br>> +  REG(&bus->regs->BBB_I2C_SCLH) = (divider - 5);<br>> +  printk("set clock end \n");<br>> +  return 0;<br>> +}<br>> +<br>> +static void am335x_i2c_destroy(i2c_bus *base)<br>> +{<br>> +  bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>> +  rtems_status_code sc;<br>> +  printk(" starting destroy\n");<br>> +  sc = rtems_interrupt_handler_remove(bus->irq, am335x_i2c_interrupt, bus);<br>> +  _Assert(sc == RTEMS_SUCCESSFUL);<br>> +  (void)sc;<br>> +  printk("end destroy\n");<br>> +  i2c_bus_destroy_and_free(&bus->base);<br>> +}<br>> +<br>> +int am335x_i2c_bus_register(<br>> +  const char *bus_path,<br>> +  uintptr_t register_base,<br>> +  uint32_t input_clock,<br>> +  rtems_vector_number irq<br>> +)<br>> +{<br>> +<br>> +  bbb_i2c_bus *bus;<br>> +  rtems_status_code sc;<br>> +  int err;<br>> +  /*check bus number is >0 & <MAX*/<br>> +<br>> +  bus = (bbb_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus));<br>> +<br>> +  if (bus == NULL) {<br>> +    return -1;<br>> +  }<br>> +<br>> +  bus->regs = (volatile bbb_i2c_regs *) register_base;<br>> +<br>> +// 1. Enable clock for I2CX<br>> +  I2C0ModuleClkConfig();<br>> +// 2. pinmux setup<br>> +  am335x_i2c0_pinmux(bus);<br>> +// 3. RESET : Disable Master, autoideal<br>> +  am335x_i2c_reset(bus);<br>> +// 4. configure bus speed<br>> +  bus->input_clock = input_clock; // By default 100KHz. Normally pass 100KHz as argument<br>> +<br>> +  printk("Before set clock \n");<br>> +  err = am335x_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT);<br>> +<br>> +  if (err != 0) {<br>> +    (*bus->base.destroy)(&bus->base);<br>> +<br>> +    rtems_set_errno_and_return_minus_one(-err);<br>> +  }<br>> +   bus->irq = irq;<br>> +<br>> +  //bring I2C out of reset<br>> +<br>> +   REG(&bus->regs->BBB_I2C_CON) |= AM335X_I2C_CON_I2C_EN;<br>> +<br>> +  // 5. Start interrupt service routine & one interrupt at a time<br>> +  sc  = rtems_interrupt_handler_install(<br>> +    irq,<br>> +    "BBB I2C",<br>> +    RTEMS_INTERRUPT_UNIQUE,<br>> +    am335x_i2c_interrupt,<br>> +    bus<br>> +   );<br>> +<br>> +  if (sc != RTEMS_SUCCESSFUL) {<br>> +    (*bus->base.destroy)(&bus->base);<br>> +<br>> +    rtems_set_errno_and_return_minus_one(EIO);<br>> +  }<br>> +  // 6. start transfer for reading and writing<br>> +  bus->base.transfer = am335x_i2c_transfer;<br>> +  bus->base.set_clock = am335x_i2c_set_clock;<br>> +  bus->base.destroy = am335x_i2c_destroy;<br>> +  printk("exit register\n");<br>> +  return i2c_bus_register(&bus->base,bus_path);<br>> +}<br>> diff --git a/c/src/lib/libbsp/arm/beagle/include/i2c.h b/c/src/lib/libbsp/arm/beagle/include/i2c.h<br>> index e7d1716..d4a9e32 100644<br>> --- a/c/src/lib/libbsp/arm/beagle/include/i2c.h<br>> +++ b/c/src/lib/libbsp/arm/beagle/include/i2c.h<br>> @@ -1,5 +1,5 @@<br>>  /**<br>> - * @file<br>> +<br>>   *<br>>   * @ingroup arm_beagle<br>>   *<br>> @@ -24,7 +24,7 @@<br>>  #define LIBBSP_ARM_BEAGLE_I2C_H<br>><br>>  #include <rtems.h><br>> -<br>> +#include <dev/i2c/i2c.h><br>>  #include <bsp.h><br>><br>>  #ifdef __cplusplus<br>> @@ -180,20 +180,8 @@ struct i2c {<br>>    unsigned short res15;<br>>  };<br>><br>> -static unsigned short wait_for_pin( void );<br>> -<br>> -static void wait_for_bb( void );<br>> -<br>> -static void flush_fifo( void );<br>> -<br>>  void i2c_init( int speed, int slaveadd );<br>><br>> -static int i2c_read_byte(<br>> -  unsigned char devaddr,<br>> -  unsigned char regoffset,<br>> -  unsigned char *value<br>> -);<br>> -<br>>  int i2c_write(<br>>    unsigned char chip,<br>>    unsigned int addr,<br>> @@ -210,10 +198,6 @@ int i2c_read(<br>>    int len<br>>  );<br>><br>> -static int imw ( unsigned char  chip, unsigned long addr, unsigned char byte );<br>> -<br>> -static int imd( unsigned char chip, unsigned int addr, unsigned int length );<br>> -<br>>  /**<br>>   * @brief Initializes the I2C module @a i2c.<br>>   *<br>> @@ -361,6 +345,139 @@ static inline rtems_status_code beagle_i2c_read(<br>>    return beagle_i2c_write_and_read(i2c, addr, NULL, 0, in, in_size);<br>>  }<br>><br>> +#define BBB_I2C_SYSCLK 48000000<br>> +#define BBB_I2C_INTERNAL_CLK 12000000<br>> +#define BBB_I2C_SPEED_CLK 100000<br>> +<br>> +#define BBB_I2C_IRQ_ERROR \<br>> +  (AM335X_I2C_IRQSTATUS_NACK \<br>> +    | AM335X_I2C_IRQSTATUS_ROVR \<br>> +    | AM335X_I2C_IRQSTATUS_AL \<br>> +    | AM335X_I2C_IRQSTATUS_ARDY \<br>> +    | AM335X_I2C_IRQSTATUS_RRDY \<br>> +    | AM335X_I2C_IRQSTATUS_XRDY \<br>> +    | AM335X_I2C_IRQSTATUS_XUDF)<br>> +<br>> +#define BBB_I2C_IRQ_USED \<br>> +  ( BBB_I2C_IRQ_ERROR \<br>> +    | AM335X_I2C_IRQSTATUS_AAS \<br>> +    | AM335X_I2C_IRQSTATUS_BF \<br>> +    | AM335X_I2C_IRQSTATUS_STC \<br>> +    | AM335X_I2C_IRQSTATUS_GC \<br>> +    | AM335X_I2C_IRQSTATUS_XDR \<br>> +    | AM335X_I2C_IRQSTATUS_RDR)<br>> +<br>> +#define BBB_I2C_0_BUS_PATH "/dev/i2c-0"<br>> +#define BBB_I2C_1_BUS_PATH "/dev/i2c-1"<br>> +#define BBB_I2C_2_BUS_PATH "/dev/i2c-2"<br>> +<br>> +#define BBB_I2C0_IRQ 70<br>> +#define BBB_I2C1_IRQ 71<br>> +#define BBB_I2C2_IRQ 30<br>> +<br>> +#define MODE2 2<br>> +#define MODE3 3<br>> +<br>> +typedef enum {<br>> +  I2C0,<br>> +  I2C1,<br>> +  I2C2,<br>> +  I2C_COUNT<br>> +}bbb_i2c_id_t;<br>> +<br>> +typedef struct i2c_regs<br>> +{<br>> +  uint32_t BBB_I2C_REVNB_LO; // 0h<br>> +  uint32_t BBB_I2C_REVNB_HI; //4h<br>> +  uint32_t dummy1[2];<br>> +  uint32_t BBB_I2C_SYSC;  // 10h =16<br>> +  uint32_t dummy2[4];<br>> +  uint32_t BBB_I2C_IRQSTATUS_RAW;  //24h =36<br>> +  uint32_t BBB_I2C_IRQSTATUS;  //28h =40<br>> +  uint32_t BBB_I2C_IRQENABLE_SET;  //2Ch =44<br>> +  uint32_t BBB_I2C_IRQENABLE_CLR; //30h =48<br>> +  uint32_t BBB_I2C_WE;  // 34h = 52<br>> +  uint32_t BBB_I2C_DMARXENABLE_SET; //38h = 56<br>> +  uint32_t BBB_I2C_DMATXENABLE_SET;  //3Ch = 60<br>> +  uint32_t BBB_I2C_DMARXENABLE_CLR;  //40h = 64<br>> +  uint32_t BBB_I2C_DMATXENABLE_CLR;  //44h = 68<br>> +  uint32_t BBB_I2C_DMARXWAKE_EN;  //48h = 72<br>> +  uint32_t BBB_I2C_DMATXWAKE_EN;  //4Ch =76<br>> +  uint32_t dummy3[16];<br>> +  uint32_t BBB_I2C_SYSS;  // 90h =144<br>> +  uint32_t BBB_I2C_BUF;  // 94h =148<br>> +  uint32_t BBB_I2C_CNT;  // 98h =152<br>> +  uint32_t BBB_I2C_DATA; //9Ch =156<br>> +  uint32_t dummy4;<br>> +  uint32_t BBB_I2C_CON;  // A4h = 164<br>> +  uint32_t BBB_I2C_OA;  //A8h = 168<br>> +  uint32_t BBB_I2C_SA;  //ACh = 172<br>> +  uint32_t BBB_I2C_PSC;  //B0h = 176<br>> +  uint32_t BBB_I2C_SCLL;  //B4h = 180<br>> +  uint32_t BBB_I2C_SCLH;  //B8h = 184<br>> +  uint32_t BBB_I2C_SYSTEST;  //BCh = 188<br>> +  uint32_t BBB_I2C_BUFSTAT;  //C0h 192<br>> +  uint32_t BBB_I2C_OA1;  //C4h 196<br>> +  uint32_t BBB_I2C_OA2;  //C8h 200<br>> +  uint32_t BBB_I2C_OA3;  //CCh 204<br>> +  uint32_t BBB_I2C_ACTOA;  //D0h 208<br>> +  uint32_t BBB_I2C_SBLOCK;  //D4h 212<br>> +}bbb_i2c_regs;<br>> +<br>> +typedef struct bbb_i2c_bus{<br>> +  i2c_bus base;<br>> +  volatile bbb_i2c_regs *regs;<br>> +  i2c_msg *msgs;<br>> +  uint32_t msg_todo;<br>> +  uint32_t current_msg_todo; // current_data_size<br>> +  uint8_t *current_msg_byte; // current_data<br>> +  uint32_t current_todo;<br>> +  bool read;<br>> +  bool hold;<br>> +  rtems_id task_id;<br>> +  rtems_vector_number irq;<br>> +  uint32_t input_clock;<br>> +  uint32_t already_transferred;<br>> +} bbb_i2c_bus;<br>> +<br>> +int am335x_i2c_bus_register(<br>> +  const char *bus_path,<br>> +  uintptr_t register_base,<br>> +  uint32_t input_clock,<br>> +  rtems_vector_number irq<br>> +);<br>> +<br>> +static inline int bbb_register_i2c_0(void)<br>> +{<br>> +  return am335x_i2c_bus_register(<br>> +    BBB_I2C_0_BUS_PATH,<br>> +    AM335X_I2C0_BASE,<br>> +    I2C_BUS_CLOCK_DEFAULT,<br>> +    BBB_I2C0_IRQ<br>> +  );<br>> +}<br>> +<br>> +static inline int bbb_register_i2c_1(void)<br>> +{<br>> +  return am335x_i2c_bus_register(<br>> +    BBB_I2C_1_BUS_PATH,<br>> +    AM335X_I2C1_BASE,<br>> +    I2C_BUS_CLOCK_DEFAULT,<br>> +    BBB_I2C1_IRQ<br>> +  );<br>> +}<br>> +<br>> +static inline int bbb_register_i2c_2(void)<br>> +{<br>> +  return am335x_i2c_bus_register(<br>> +    BBB_I2C_2_BUS_PATH,<br>> +    AM335X_I2C2_BASE,<br>> +    I2C_BUS_CLOCK_DEFAULT,<br>> +    BBB_I2C2_IRQ<br>> +  );<br>> +}<br>> +<br>> +<br>>  #ifdef __cplusplus<br>>  }<br>>  #endif /* __cplusplus */<br>> --<br>> 2.7.4<br>><br>><br>> From 6855dbe659d67e304cf05474b2753b4239ceca90 Mon Sep 17 00:00:00 2001<br>> From: Sichen Zhao <1473996754@qq.com><br>> Date: Thu, 30 Mar 2017 11:08:32 +0800<br>> Subject: [PATCH 2/2] Beaglebone Black i2c code, modify by Sichen Zhao - Modify<br>>  the bbb-i2c.c code, base on Punit Vara code - Modify the include/i2c.h, base<br>>  on Punit Vara code I2C is working now, BBB can read the EEPROM by i2c The<br>>  test suite code link: https://github.com/hahchenchen/rtems/tree/i2c_1.0/i2c0<br>><br>> ---<br>>  c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c | 370 ++++++++++++------------------<br>>  c/src/lib/libbsp/arm/beagle/include/i2c.h |  11 +-<br>>  2 files changed, 150 insertions(+), 231 deletions(-)<br>><br>> diff --git a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c<br>> index cd1e9c1..4d22831 100644<br>> --- a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c<br>> +++ b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c<br>> @@ -21,80 +21,8 @@<br>>  #include <bsp/bbb-gpio.h><br>>  #include <rtems/score/assert.h><br>><br>> -/*<br>> -static bool am335x_i2c_pinmux(bbb_i2c_bus *bus)<br>> -{<br>> -  bool status =true;<br>> -    // We will check i2c_bus_id in am335x_i2c_bus_register<br>> -    // Apart from mode and pull_up register what about SCREWCTRL & RXACTIVE ??<br>> -  if (bus->i2c_bus_id == I2C1) {<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_CS0) = (BBB_MUXMODE(MODE2) | BBB_PU_EN);<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D1) = (BBB_MUXMODE(MODE2) | BBB_PU_EN);<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_TXD) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RXD) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> -  } else if (bus->i2c_bus_id == I2C2) {<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RTSN) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_CTSN) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> -    REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) = (BBB_MUXMODE(MODE3) | BBB_PU_EN);<br>> -  } else {<br>> -  status = false;<br>> -  }<br>> -  return status;<br>> -}<br>> -*/<br>><br>> -/* ref. Table 21-4 I2C Clock Signals */<br>> -/*<br>> - For I2C1/2<br>> - Interface clock - 100MHz - CORE_LKOUTM4 / 2 - pd_per_l4ls_gclk<br>> - Functional clock - 48MHz - PER_CLKOUTM2 / 4 - pd_per_ic2_fclk<br>> -*/<br>> -<br>> -/*<br>> -static void am335x_i2c1_i2c2_module_clk_config(bbb_i2c_bus *bus)<br>> -{<br>> -*/<br>> -/*0x2 = SW_WKUP : SW_WKUP: Start a software forced wake-up<br>> -transition on the domain. */<br>> -/*<br>> -  REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) |=<br>> -                        AM335X_CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP;<br>> -  while((REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) &<br>> -                        AM335X_CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL) !=<br>> -                        AM335X_CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP);<br>> -*/<br>> -<br>> -/* 0x2 = ENABLE : Module is explicitly enabled. Interface clock (if not<br>> -used for functions) may be gated according to the clock domain<br>> -state. Functional clocks are guarantied to stay present. As long as in<br>> -this configuration, power domain sleep transition cannot happen.*/<br>> - /* REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKCTRL) |=<br>> -                        AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE;<br>> -  while((REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKCTRL) &<br>> -      AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE) != AM335X_CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE);<br>> -*/<br>> -/*0x2 = ENABLE : Module is explicitly enabled. Interface clock (if not<br>> -used for functions) may be gated according to the clock domain<br>> -state. Functional clocks are guarantied to stay present. As long as in<br>> -this configuration, power domain sleep transition cannot happen.*/<br>> -/*<br>> -  if (bus->i2c_bus_id == I2C1) {<br>> -  REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C1_CLKCTRL) |=<br>> -                             AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE;<br>> -  while(REG((AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C1_CLKCTRL) &<br>> -     AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE) != AM335X_CM_PER_I2C1_CLKCTRL_MODULEMODE_ENABLE);<br>> -  } else if (bus->i2c_bus_id == I2C2) {<br>> -  REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C2_CLKCTRL) |=<br>> -                             AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE;<br>> -  while(REG((AM335X_CM_PER_ADDR + AM335X_CM_PER_I2C2_CLKCTRL) &<br>> -     AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE) != AM335X_CM_PER_I2C2_CLKCTRL_MODULEMODE_ENABLE);<br>> -  while(!(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_L4LS_CLKSTCTRL) &<br>> -           (AM335X_CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |<br>> -            AM335X_CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_I2C_FCLK)));<br>> -  }<br>> -}<br>> -*/<br>> +static void flush_fifo(i2c_bus *base);<br>><br>>  static void am335x_i2c0_pinmux(bbb_i2c_bus *bus)<br>>  {<br>> @@ -295,43 +223,59 @@ static void I2C0ModuleClkConfig(void)<br>>             CM_WKUP_I2C0_CLKCTRL_IDLEST));<br>>  }<br>><br>> -/*<br>> -void am335x_i2c_init(bbb_i2c_bus *bus, uint32_t input_clock)<br>> -{<br>> -  // am335x_i2c_pinmux()<br>> -  // am335x_i2c1_i2c2_module_clk_config<br>> -}<br>> -*/<br>> +<br>><br>>  static bool am335x_i2c_busbusy(volatile bbb_i2c_regs *regs)<br>>  {<br>>    bool status;<br>> +  int stat;<br>> +  int timeout=I2C_TIMEOUT;<br>> +<br>><br>> -  if (REG(&regs->BBB_I2C_IRQSTATUS_RAW) & AM335X_I2C_IRQSTATUS_RAW_BB)<br>> +   while ((stat = readw(&regs->BBB_I2C_IRQSTATUS_RAW) &<br>> +    AM335X_I2C_IRQSTATUS_RAW_BB) && timeout--) {<br>> +<br>> +    writew(stat, &regs->BBB_I2C_IRQSTATUS);<br>> +    udelay(100);<br>> +  }<br>> +<br>> +  if (timeout <= 0) {<br>> +    printf("Timed out in wait_for_bb: status=%04x\n",<br>> +           stat);<br>> +   status = true;<br>> +  }<br>> +  else<br>>    {<br>> -    status = true;<br>> -  } else {<br>> -    status = false;<br>> +  writew(0xFFFF, &regs->BBB_I2C_IRQSTATUS);   /* clear delayed stuff*/<br>> +   status = false;<br>>    }<br>> +<br>>    return status;<br>>  }<br>><br>>  static void am335x_i2c_reset(bbb_i2c_bus *bus)<br>>  {<br>>    volatile bbb_i2c_regs *regs = bus->regs;<br>> -  printk("reset bus->reg is %x \n",bus->regs);<br>> -  /* Disable I2C module at the time of initialization*/<br>> -  /*Should I use write32 ?? I guess mmio_clear is correct choice here*/<br>> -  printk("inside BBB_I2C_CON value is %x \n",&regs->BBB_I2C_CON);<br>> -  mmio_clear((&regs->BBB_I2C_CON),AM335X_I2C_CON_I2C_EN);<br>> -  mmio_clear((&regs->BBB_I2C_SYSC),AM335X_I2C_SYSC_AUTOIDLE);<br>> -  //REG(bus->regs + AM335X_I2C_CON) &= ~(AM335X_I2C_CON_I2C_EN);<br>> -  //REG(bus->regs + AM335X_I2C_SYSC) &= ~(AM335X_I2C_SYSC_AUTOIDLE);<br>> -<br>> -  /*<br>> -  can I clear all the interrupt here ?<br>> -  mmio_write(get_reg_addr(bbb_i2c_bus->reg->AM335X_I2C_IRQ_ENABLE_CLR), ??)<br>> -  */<br>> +   int timeout = I2C_TIMEOUT;<br>> +<br>> +   if (readw(&regs->BBB_I2C_CON) & I2C_CON_EN) {<br>> +    writew(0, &regs->BBB_I2C_CON);<br>> +    udelay(50000);<br>> +  }<br>> +<br>> +  writew(0x2, &regs->BBB_I2C_SYSC); /* for ES2 after soft reset */<br>> +  udelay(1000);<br>> +<br>> +  writew(I2C_CON_EN, &regs->BBB_I2C_CON);<br>> +  while (!(readw(&regs->BBB_I2C_SYSS) & I2C_SYSS_RDONE) && timeout--) {<br>> +    if (timeout <= 0) {<br>> +      puts("ERROR: Timeout in soft-reset\n");<br>> +      return;<br>> +    }<br>> +    udelay(1000);<br>> +  }<br>> +<br>> +<br>>  }<br>><br>>  /*<br>> @@ -360,7 +304,7 @@ static void am335x_i2c_next_byte(bbb_i2c_bus *bus)<br>>  {<br>>    i2c_msg *msg;<br>><br>> -  printk("Enter next_byte\n");<br>> +<br>>    ++bus->msgs;<br>>    --bus->msg_todo;<br>><br>> @@ -402,61 +346,26 @@ static void am335x_clean_interrupts(volatile bbb_i2c_regs *regs)<br>>  static void am335x_i2c_setup_read_transfer(bbb_i2c_bus *bus, volatile bbb_i2c_regs *regs, const i2c_msg *msgs, bool send_stop)<br>>  {<br>>    volatile unsigned int no_bytes;<br>> -  //am335x_i2c_masterint_enable(regs, AM335X_I2C_INT_RECV_READY);<br>> -   // No of data to be transmitted at a time<br>> -  REG(&regs->BBB_I2C_CNT) = 0x02;<br>> -  no_bytes = REG(&regs->BBB_I2C_CNT);<br>> -<br>> -  // I2C Controller in Master Mode<br>> -  REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_START | AM335X_I2C_CON_MST;<br>> -  printk("set master in transmission mode %x \n",REG(&regs->BBB_I2C_CON));<br>> -<br>> -  // Set Slave address & Master enable, bring out of reset<br>> -  REG(&regs->BBB_I2C_SA) = msgs->addr;<br>> -  printf("slave address : %x\n",REG(&regs->BBB_I2C_SA));<br>> +  int status;<br>><br>> -  // clear status of all interrupts<br>> -  am335x_clean_interrupts(regs);<br>> -  printk("\n set memory address to read\n");<br>> -<br>> -  // transmit interrupt is enabled<br>> -  am335x_i2c_masterint_enable(regs,AM335X_I2C_IRQSTATUS_XRDY);<br>> -  printk("Enable transmit interrupt \n");<br>> -  //start condition<br>> -  REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;<br>> -  printk("start transmission \n");<br>> -  while(am335x_i2c_busbusy(regs) == 0);<br>> -  printk("bus is free \n");<br>> -  printk("CNT : %x\n", no_bytes);<br>> -  while(0 != no_bytes);<br>> -  printk("total msg count for tranmission is zero \n");<br>> -  while( !(am335x_i2c_intrawstatus(regs) & (AM335X_I2C_IRQSTATUS_ARDY)));<br>> +    REG(&regs->BBB_I2C_CNT) = bus->current_msg_todo;<br>><br>> -  printk("Enter read transfer \n");<br>> -   // No of data to be received at a time(msg_count!!)<br>> -  printk("msg_todo for read is %d \n",bus->msg_todo);<br>> -  REG(&regs->BBB_I2C_CNT) = bus->msg_todo;<br>> -<br>> -  // clear status of all interrupts<br>> -  //am335x_clean_interrupts(regs);<br>> -<br>>    // I2C Controller in Master Mode<br>>    REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_RX | AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_MST;<br>> -  printk("Set master to receiver mode %x \n", REG(&regs->BBB_I2C_CON));<br>> +<br>>    // receive interrupt is enabled<br>>    am335x_i2c_masterint_enable(regs, AM335X_I2C_INT_RECV_READY | AM335X_I2C_INT_STOP_CONDITION);<br>> -<br>> +<br>> +<br>>    if (send_stop) {<br>>      // stop condition<br>> -    printk("stop to read\n");<br>>      REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>>    } else {<br>>      // start condition<br>> -    printk("start to read\n");<br>>      REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;<br>>    }<br>> -  while(am335x_i2c_busbusy(regs) == 0);<br>> -  printk("Exit read transfer\n");<br>> +<br>> +<br>>  }<br>><br>><br>> @@ -465,85 +374,63 @@ static void am335x_i2c_continue_read_transfer(<br>>    volatile bbb_i2c_regs *regs<br>>  )<br>>  {<br>> -  printk("enter continue read transfer \n");<br>> +<br>>    bus->current_msg_byte[bus->already_transferred] = REG(&regs->BBB_I2C_DATA);<br>> +<br>>    bus->already_transferred++;<br>>    am335x_int_clear(regs,AM335X_I2C_INT_RECV_READY);<br>> -  printk("clear RRDY in continue read transfer\n");<br>> +<br>><br>>    if (bus->already_transferred == REG(&regs->BBB_I2C_CNT)) {<br>> -    printk("continue read transfer finished \n");<br>> -    //am335x_i2c_setup_read_transfer(bus,regs,false);<br>> +<br>> +<br>>      am335x_i2c_masterint_disable(regs, AM335X_I2C_INT_RECV_READY);<br>> -    printk("disable RRDY in continue read transfer\n");<br>> +<br>>      REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> -    printk("stop condition in continue read transfer %x\n",REG(&regs->BBB_I2C_CON));<br>> +<br>>    }<br>>  }<br>><br>> +<br>>  static void am335x_i2c_continue_write(bbb_i2c_bus *bus, volatile bbb_i2c_regs *regs)<br>>  {<br>> -   REG(&regs->BBB_I2C_DATA) = 0x00;<br>> -   am335x_int_clear(regs, AM335X_I2C_IRQSTATUS_XRDY);<br>> -   printk("clear XRDY continue write\n");<br>> -   /*<br>> -   if (bus->already_transferred == REG(&regs->BBB_I2C_CNT)) {<br>> -   printk("\n finished transfer \n");<br>> -   am335x_i2c_masterint_disable(regs, AM335X_I2C_IRQSTATUS_XRDY);<br>> -   printk("disable XRDY continue write \n");<br>> -   REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> -   } else {<br>> -     printk("write memory address \n");<br>> -     REG(&regs->BBB_I2C_DATA) = *bus->current_msg_byte;<br>> -  }<br>> -   */<br>><br>> -  /*<br>> -   if (bus->already_transferred == bus->msg_todo) {<br>> -     printk("finished transfer \n");<br>> -     am335x_int_clear(regs, AM335X_I2C_IRQSTATUS_XRDY);<br>> -     REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_STOP;<br>> -   } else {<br>> -     printk("remaining byte \n");<br>> -     REG(&regs->BBB_I2C_DATA) = bus->current_msg_byte[bus->already_transferred];<br>> -     printk("%s",REG(&regs->BBB_I2C_DATA));<br>> -     bus->already_transferred++;<br>> -   }<br>> -   */<br>> +<br>> +  writeb(0x0,&regs->BBB_I2C_DATA);<br>> +<br>> +   writew(AM335X_I2C_IRQSTATUS_XRDY, &regs->BBB_I2C_IRQSTATUS);<br>> +<br>> +<br>>  }<br>><br>> -static void am335x_i2c_setup_write_transfer(bbb_i2c_bus *bus,volatile bbb_i2c_regs *regs)<br>> +static void am335x_i2c_setup_write_transfer(bbb_i2c_bus *bus,volatile bbb_i2c_regs *regs, const i2c_msg *msgs)<br>>  {<br>>    volatile unsigned int no_bytes;<br>> -  printk(" \n Enter write transfer \n");<br>><br>> +<br>>    // Following data count specify bytes to be transmitted<br>> -  REG(&regs->BBB_I2C_CNT) = bus->msg_todo;<br>> +  REG(&regs->BBB_I2C_CNT) = bus->current_msg_todo;<br>>    no_bytes = REG(&regs->BBB_I2C_CNT);<br>> -  // clear status of all interrupts<br>> -  // Already cleaned during reset<br>> -  am335x_clean_interrupts(regs);<br>> -<br>> +  REG(&regs->BBB_I2C_SA) = msgs->addr;<br>> +<br>>    // I2C Controller in Master transmitter Mode<br>>    REG(&regs->BBB_I2C_CON) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN;<br>> -  printk("enable master in transmiter mode setup write %x\n",REG(&regs->BBB_I2C_CON));<br>> +<br>> +  am335x_clean_interrupts(regs);<br>><br>>    // transmit interrupt is enabled<br>> -  am335x_i2c_masterint_enable(regs,AM335X_I2C_IRQSTATUS_XRDY);<br>> -  printk("enable XRDY setup write\n");<br>> +  am335x_i2c_masterint_enable(regs,AM335X_I2C_IRQSTATUS_XRDY );<br>> +<br>><br>>    //start condition<br>>    REG(&regs->BBB_I2C_CON) |= AM335X_I2C_CON_START;<br>> -  printk("set start condition in setup write %x \n",REG(&regs->BBB_I2C_CON));<br>> +<br>><br>> -  while(am335x_i2c_busbusy(regs) == 0);<br>> -  printk("CNT in setup write : %x \n",REG(&regs->BBB_I2C_CNT));<br>> -  printk("setup write msg_todo %x \n",bus->current_todo);<br>> -  while(0 != no_bytes);<br>> -  printk("check whether ???\n");<br>> -  printk("RAW =  %x",REG(&regs->BBB_I2C_IRQSTATUS_RAW));<br>> +  while(am335x_i2c_busbusy(regs)==0);<br>> +<br>> +<br>>    while( !((am335x_i2c_intrawstatus(regs)) & (AM335X_I2C_IRQSTATUS_ARDY)));<br>> -  printk("exit setup write \n");<br>> +<br>>  }<br>><br>><br>> @@ -554,9 +441,7 @@ static void am335x_i2c_setup_transfer(bbb_i2c_bus *bus, volatile bbb_i2c_regs *r<br>>    bool send_stop = false;<br>>    uint32_t i;<br>><br>> -  printk("Enter setup transfer\n");<br>>    bus->current_todo = msgs[0].len;<br>> -<br>>    for (i = 1; i < msg_todo && (msgs[i].flags & I2C_M_NOSTART) != 0; ++i) {<br>>      bus->current_todo += msgs[i].len;<br>>    }<br>> @@ -566,18 +451,22 @@ static void am335x_i2c_setup_transfer(bbb_i2c_bus *bus, volatile bbb_i2c_regs *r<br>>    REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_TXFIFO_CLR;<br>>    REG(&bus->regs->BBB_I2C_BUF) |= AM335X_I2C_BUF_RXFIFO_CLR;<br>>    am335x_i2c_set_address_size(msgs,regs);<br>> -  bus->read = ((bus->read == true) ? 0:1);<br>> +<br>> +<br>> +  bus->read = (msgs->flags & I2C_M_RD) != 0;<br>> +<br>>    bus->already_transferred = (bus->read == true) ? 0 : 1;<br>><br>>    if (bus->read) {<br>>      if (REG(&regs->BBB_I2C_CNT) == 1) {<br>> +<br>>        send_stop = true;<br>>      }<br>> -    printk("configure to read bus\n");<br>> +<br>>      am335x_i2c_setup_read_transfer(bus,regs,msgs,send_stop);<br>>    } else {<br>> -    printk("configure to write bus\n");<br>> -    am335x_i2c_setup_write_transfer(bus,regs);<br>> +<br>> +    am335x_i2c_setup_write_transfer(bus,regs,msgs);<br>>    }<br>><br>>  }<br>> @@ -589,42 +478,45 @@ static void am335x_i2c_interrupt(void *arg)<br>>    /* get status of enabled interrupts */<br>>    uint32_t irqstatus = REG(&regs->BBB_I2C_IRQSTATUS);<br>>    bool done = false;<br>> -  printk("\n inside interrupt function \n");<br>>    /* Clear all enabled interrupt except receive ready and transmit ready interrupt in status register */<br>> -  REG(&regs->BBB_I2C_IRQSTATUS) = (irqstatus & ~(AM335X_I2C_IRQSTATUS_RRDY | AM335X_I2C_IRQSTATUS_XRDY));<br>> -  printk("\n irqstatus = %x \n",REG(&regs->BBB_I2C_IRQSTATUS));<br>> +  REG(&regs->BBB_I2C_IRQSTATUS) = (irqstatus & ~( AM335X_I2C_IRQSTATUS_RRDY | AM335X_I2C_IRQSTATUS_XRDY));<br>><br>>    if (irqstatus & AM335X_I2C_INT_RECV_READY) {<br>> -     printk("\nInside receive interrupt\n");<br>> +   delay_bbb_i2c<br>> +<br>>      am335x_i2c_continue_read_transfer(bus, regs);<br>>    }<br>><br>>    if (irqstatus & AM335X_I2C_IRQSTATUS_XRDY) {<br>> -    printk("\ninside transmit interrupt \n");<br>> +<br>>      am335x_i2c_continue_write(bus,regs);<br>>    }<br>><br>>    if (irqstatus & AM335X_I2C_IRQSTATUS_NACK) {<br>>      done = true;<br>> -    printk("inside NACK\n");<br>> +<br>>      am335x_i2c_masterint_disable(regs,AM335X_I2C_IRQSTATUS_NACK);<br>>    }<br>><br>> +  if (irqstatus & AM335X_I2C_IRQSTATUS_ARDY) {<br>> +   done = true;<br>> +  writew(I2C_STAT_ARDY, &regs->BBB_I2C_IRQSTATUS);<br>> +  }<br>> +<br>> +<br>>    if (irqstatus & AM335X_I2C_IRQSTATUS_BF) {<br>>      done = true;<br>> -    printk("inside BF \n ");<br>> +<br>>    }<br>><br>>    if (done) {<br>>      uint32_t err = irqstatus & BBB_I2C_IRQ_ERROR;<br>> -    printk("interrupt done \n");<br>> -<br>> +<br>>      am335x_i2c_next_byte(bus);<br>><br>> -    if (bus->msg_todo == 0 || err != 0) {<br>> +    if (bus->msg_todo == 0 ) {<br>>      rtems_status_code sc;<br>> -<br>> -    // am335x_i2c_disable_interrupts(regs);<br>> +<br>>      am335x_i2c_masterint_disable(regs, (AM335X_I2C_IRQSTATUS_RRDY | AM335X_I2C_IRQSTATUS_XRDY | AM335X_I2C_IRQSTATUS_BF));<br>><br>>      REG(&regs->BBB_I2C_IRQSTATUS) = err;<br>> @@ -633,6 +525,7 @@ static void am335x_i2c_interrupt(void *arg)<br>>      _Assert(sc == RTEMS_SUCCESSFUL);<br>>      (void) sc;<br>>      } else {<br>> +<br>>        am335x_i2c_setup_transfer(bus, regs);<br>>      }<br>>    }<br>> @@ -644,7 +537,6 @@ static int am335x_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)<br>>    bbb_i2c_bus *bus = (bbb_i2c_bus *)base;<br>>    volatile bbb_i2c_regs *regs;<br>>    uint32_t i;<br>> - printk("\n enter transfer ");<br>>    rtems_task_wake_after(1);<br>><br>><br>> @@ -660,11 +552,11 @@ static int am335x_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)<br>><br>>    bus->msgs = &msgs[0];<br>>    bus->msg_todo = msg_count;<br>> -  printk("total msg = msg_count : %x \n",bus->msg_todo);<br>> +<br>> +<br>>    bus->current_msg_todo = msgs[0].len;// current data size<br>>    bus->current_msg_byte = msgs[0].buf;// current data<br>> -  printk("\n current_msg_todo %x \n ",msgs[0].len);<br>> -  printk("\n current_msg_byte %x \n ",msgs[0].buf);<br>> +<br>>    bus->task_id = rtems_task_self();<br>><br>>    regs = bus->regs;<br>> @@ -680,8 +572,6 @@ static int am335x_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)<br>><br>>      return -ETIMEDOUT;<br>>    }<br>> -  printk("exit transfer\n");<br>> -  // return bus->regs->BBB_I2C_IRQSTATUS == 0 ? 0 : -EIO;<br>>    return 0;<br>>  }<br>><br>> @@ -691,21 +581,17 @@ static int am335x_i2c_set_clock(i2c_bus *base, unsigned long clock)<br>>    volatile bbb_i2c_regs *regs = bus->regs;<br>>    uint32_t prescaler,divider;<br>><br>> -  printk("set clock start\n");<br>> +<br>>    prescaler = (BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK) -1;<br>> -  printk("PSC offset %x \n ",&regs->BBB_I2C_PSC);<br>> -  printk("PSC offset %x \n", &bus->regs->BBB_I2C_PSC);<br>> -  //mmio_write((&regs->BBB_I2C_PSC), prescaler);<br>> +<br>>    REG(&bus->regs->BBB_I2C_PSC) = prescaler;<br>><br>>    divider = BBB_I2C_INTERNAL_CLK/(2*clock);<br>> -  printk("SCLL offset %x \n",&bus->regs->BBB_I2C_SCLL);<br>> -  //mmio_write((&regs->BBB_I2C_SCLL), (divider - 7));<br>> +<br>>    REG(&bus->regs->BBB_I2C_SCLL) = (divider - 7);<br>> -  //mmio_write((&regs->BBB_I2C_SCLH), (divider - 5));<br>> -  printk("SCHL offset %x\n",&bus->regs->BBB_I2C_SCLH);<br>> +<br>>    REG(&bus->regs->BBB_I2C_SCLH) = (divider - 5);<br>> -  printk("set clock end \n");<br>> +<br>>    return 0;<br>>  }<br>><br>> @@ -713,11 +599,11 @@ static void am335x_i2c_destroy(i2c_bus *base)<br>>  {<br>>    bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>>    rtems_status_code sc;<br>> -  printk(" starting destroy\n");<br>> +<br>>    sc = rtems_interrupt_handler_remove(bus->irq, am335x_i2c_interrupt, bus);<br>>    _Assert(sc == RTEMS_SUCCESSFUL);<br>>    (void)sc;<br>> -  printk("end destroy\n");<br>> +<br>>    i2c_bus_destroy_and_free(&bus->base);<br>>  }<br>><br>> @@ -751,7 +637,7 @@ int am335x_i2c_bus_register(<br>>  // 4. configure bus speed<br>>    bus->input_clock = input_clock; // By default 100KHz. Normally pass 100KHz as argument<br>><br>> -  printk("Before set clock \n");<br>> +<br>>    err = am335x_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT);<br>><br>>    if (err != 0) {<br>> @@ -763,7 +649,11 @@ int am335x_i2c_bus_register(<br>><br>>    //bring I2C out of reset<br>><br>> -   REG(&bus->regs->BBB_I2C_CON) |= AM335X_I2C_CON_I2C_EN;<br>> +   udelay(1000);<br>> +  flush_fifo(&bus->base);<br>> +  writew(0xFFFF, &bus->regs->BBB_I2C_IRQSTATUS);<br>> +<br>> +<br>><br>>    // 5. Start interrupt service routine & one interrupt at a time<br>>    sc  = rtems_interrupt_handler_install(<br>> @@ -783,6 +673,30 @@ int am335x_i2c_bus_register(<br>>    bus->base.transfer = am335x_i2c_transfer;<br>>    bus->base.set_clock = am335x_i2c_set_clock;<br>>    bus->base.destroy = am335x_i2c_destroy;<br>> -  printk("exit register\n");<br>> +<br>>    return i2c_bus_register(&bus->base,bus_path);<br>>  }<br>> +<br>> +<br>> +static void flush_fifo(i2c_bus *base)<br>> +{<br>> +  bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>> +  volatile bbb_i2c_regs *regs = bus->regs;<br>> +<br>> +<br>> +  int stat;<br>> +<br>> +  /*<br>> +   * note: if you try and read data when its not there or ready<br>> +   * you get a bus error<br>> +   */<br>> +  while (1) {<br>> +    stat = readw(&bus->regs->BBB_I2C_IRQSTATUS);<br>> +    if (stat == I2C_STAT_RRDY) {<br>> +      readb(&bus->regs->BBB_I2C_DATA);<br>> +      writew(I2C_STAT_RRDY, &bus->regs->BBB_I2C_IRQSTATUS);<br>> +      udelay(1000);<br>> +    } else<br>> +      break;<br>> +  }<br>> +}<br>> diff --git a/c/src/lib/libbsp/arm/beagle/include/i2c.h b/c/src/lib/libbsp/arm/beagle/include/i2c.h<br>> index d4a9e32..a4fcf21 100644<br>> --- a/c/src/lib/libbsp/arm/beagle/include/i2c.h<br>> +++ b/c/src/lib/libbsp/arm/beagle/include/i2c.h<br>> @@ -132,11 +132,11 @@ extern "C" {<br>><br>><br>>  #define DISP_LINE_LEN 128<br>> -#define I2C_TIMEOUT 1000<br>> +#define I2C_TIMEOUT 500<br>><br>>  #define I2C_BUS_MAX 3<br>><br>> -#define I2C_BASE1         (OMAP34XX_CORE_L4_IO_BASE + 0x070000)<br>> +#define I2C_BASE1         (OMAP34XX_CORE_L4_IO_BASE + 0x070000) //0x48000000+0x070000<br>><br>>  #define I2C_DEFAULT_BASE      I2C_BASE1<br>><br>> @@ -356,7 +356,7 @@ static inline rtems_status_code beagle_i2c_read(<br>>      | AM335X_I2C_IRQSTATUS_ARDY \<br>>      | AM335X_I2C_IRQSTATUS_RRDY \<br>>      | AM335X_I2C_IRQSTATUS_XRDY \<br>> -    | AM335X_I2C_IRQSTATUS_XUDF)<br>> +    | AM335X_I2C_IRQSTATUS_XUDF )<br>><br>>  #define BBB_I2C_IRQ_USED \<br>>    ( BBB_I2C_IRQ_ERROR \<br>> @@ -378,6 +378,8 @@ static inline rtems_status_code beagle_i2c_read(<br>>  #define MODE2 2<br>>  #define MODE3 3<br>><br>> +#define delay_bbb_i2c printf("     ");<br>> +<br>>  typedef enum {<br>>    I2C0,<br>>    I2C1,<br>> @@ -478,6 +480,9 @@ static inline int bbb_register_i2c_2(void)<br>>  }<br>><br>><br>> +<br>> +<br>> +<br>>  #ifdef __cplusplus<br>>  }<br>>  #endif /* __cplusplus */<br>> --<br>> 2.7.4<br>><br>> _______________________________________________<br>> devel mailing list<br>> devel@rtems.org<br>> http://lists.rtems.org/mailman/listinfo/devel<br></div>