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