summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/beagle/misc
diff options
context:
space:
mode:
authorClaas Ziemke <ziemke@irs.uni-stuttgart.de>2012-08-22 14:39:02 +0200
committerJoel Sherrill <joel.sherrill@oarcorp.com>2014-11-03 14:19:47 -0600
commit7a669866eea8b66b87b22015b793b5ea4ff950c1 (patch)
treef7faffb2cd20b45894ddabbc60f1a0e5ee96403d /c/src/lib/libbsp/arm/beagle/misc
parentAdd some generic ARM am335x and omap definitions (diff)
downloadrtems-7a669866eea8b66b87b22015b793b5ea4ff950c1.tar.bz2
Added BeagleBoard BSP
Coding done in course of GSoC2012. Commit edited to be brought up-to-date with mainline by Ben Gras <beng@shrike-systems.com>.
Diffstat (limited to 'c/src/lib/libbsp/arm/beagle/misc')
-rw-r--r--c/src/lib/libbsp/arm/beagle/misc/boot.c62
-rw-r--r--c/src/lib/libbsp/arm/beagle/misc/i2c.c450
-rw-r--r--c/src/lib/libbsp/arm/beagle/misc/restart.c32
-rw-r--r--c/src/lib/libbsp/arm/beagle/misc/system-clocks.c140
-rw-r--r--c/src/lib/libbsp/arm/beagle/misc/timer.c46
5 files changed, 730 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/beagle/misc/boot.c b/c/src/lib/libbsp/arm/beagle/misc/boot.c
new file mode 100644
index 0000000000..771df7007d
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/misc/boot.c
@@ -0,0 +1,62 @@
+/**
+ * @file
+ *
+ * @ingroup beagle_boot
+ *
+ * @brief Boot support implementation.
+ */
+
+/*
+ * Copyright (c) 2012 Claas Ziemke. All rights reserved.
+ *
+ * Claas Ziemke
+ * Kernerstrasse 11
+ * 70182 Stuttgart
+ * Germany
+ * <claas.ziemke@gmx.net>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+
+#include <bsp/boot.h>
+
+void beagle_setup_boot_block(
+ beagle_boot_block *boot_block,
+ uint8_t icr,
+ uint8_t page_count
+)
+{
+ memset(boot_block, 0, sizeof(*boot_block));
+
+ ++page_count;
+
+ boot_block->field.d0 = icr;
+ boot_block->field.d2 = icr;
+ boot_block->field.d4 = page_count;
+ boot_block->field.d6 = page_count;
+ boot_block->field.d8 = page_count;
+ boot_block->field.d10 = page_count;
+
+ icr = (uint8_t) ~((unsigned) icr);
+ page_count = (uint8_t) ~((unsigned) page_count);
+
+ boot_block->field.d1 = icr;
+ boot_block->field.d3 = icr;
+ boot_block->field.d5 = page_count;
+ boot_block->field.d7 = page_count;
+ boot_block->field.d9 = page_count;
+ boot_block->field.d11 = page_count;
+
+ boot_block->field.d12 = 0xaa;
+}
+
+void beagle_set_boot_block_bad(
+ beagle_boot_block *boot_block
+)
+{
+ boot_block->field.d12 = 0;
+}
diff --git a/c/src/lib/libbsp/arm/beagle/misc/i2c.c b/c/src/lib/libbsp/arm/beagle/misc/i2c.c
new file mode 100644
index 0000000000..322c501d3c
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/misc/i2c.c
@@ -0,0 +1,450 @@
+/**
+ * @file
+ *
+ * @ingroup beagle_i2c
+ *
+ * @brief I2C support implementation.
+ */
+
+/*
+ * Copyright (c) 2012 Claas Ziemke. All rights reserved.
+ *
+ * Claas Ziemke
+ * Kernerstrasse 11
+ * 70182 Stuttgart
+ * Germany
+ * <claas.ziemke@gmx.net>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+#include <bsp.h>
+#include <bsp/i2c.h>
+
+static struct i2c *i2c_base = (struct i2c *)I2C_DEFAULT_BASE;
+
+static unsigned short wait_for_pin( void ) {
+
+ unsigned short status;
+ int timeout = I2C_TIMEOUT;
+
+ do {
+ udelay( 1000 );
+ status = readw( &i2c_base->stat );
+ } while( !( status &
+ ( I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
+ I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
+ I2C_STAT_AL ) ) && timeout-- );
+
+ if( timeout <= 0 ) {
+ printk( "timed out in wait_for_pin: I2C_STAT = %x\n",
+ readw( &i2c_base->stat ) );
+ writew( 0xFFFF, &i2c_base->stat ); /* clear current interrupts...*/
+ status = 0;
+ }
+
+ return status;
+}
+
+static void wait_for_bb( void ) {
+
+ int timeout = I2C_TIMEOUT;
+ unsigned short status;
+
+ writew( 0xFFFF, &i2c_base->stat ); /* clear current interrupts...*/
+ while( ( status = readw( &i2c_base->stat ) & I2C_STAT_BB ) && timeout-- ) {
+ writew( status, &i2c_base->stat );
+ udelay( 1000 );
+ }
+
+ if( timeout <= 0 ) {
+ printk( "timed out in wait_for_bb: I2C_STAT = %x\n",
+ readw( &i2c_base->stat ) );
+ }
+ writew( 0xFFFF, &i2c_base->stat ); /* clear delayed stuff*/
+}
+
+static void flush_fifo( void ) {
+
+ unsigned short status;
+
+ /* note: if you try and read data when its not there or ready
+ * you get a bus error
+ */
+ while( 1 ) {
+ status = readw( &i2c_base->stat );
+ if( status == I2C_STAT_RRDY ) {
+ readw( &i2c_base->data );
+ writew( I2C_STAT_RRDY, &i2c_base->stat );
+ udelay( 1000 );
+ } else {
+ break;
+ }
+ }
+}
+
+void i2c_init( int speed, int slaveadd ) {
+
+ int psc, fsscll, fssclh;
+ int hsscll = 0, hssclh = 0;
+ unsigned int scll, sclh;
+ int timeout = I2C_TIMEOUT;
+
+ // Only handle standard, fast and high speeds
+ if( ( speed != OMAP_I2C_STANDARD ) &&
+ ( speed != OMAP_I2C_FAST_MODE ) &&
+ ( speed != OMAP_I2C_HIGH_SPEED ) ) {
+ printk( "Error : I2C unsupported speed %d\n", speed );
+ return;
+ }
+
+ psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
+ psc -= 1;
+ if( psc < I2C_PSC_MIN ) {
+ printk( "Error : I2C unsupported prescalar %d\n", psc );
+ return;
+ }
+
+ if( speed == OMAP_I2C_HIGH_SPEED ) {
+ // High speed
+
+ // For first phase of HS mode
+ fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / ( 2 * OMAP_I2C_FAST_MODE );
+
+ fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
+ fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
+ if( ( ( fsscll < 0 ) || ( fssclh < 0 ) ) || ( ( fsscll > 255 ) ||
+ ( fssclh > 255 ) ) ) {
+ printk( "Error : I2C initializing first phase clock\n" );
+ return;
+ }
+
+ // For second phase of HS mode
+ hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / ( 2 * speed );
+
+ hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM;
+ hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM;
+ if( ( ( fsscll < 0 ) || ( fssclh < 0 ) ) || ( ( fsscll > 255 ) ||
+ ( fssclh > 255 ) ) ) {
+ printk( "Error : I2C initializing second phase clock\n" );
+ return;
+ }
+
+ scll = ( unsigned int ) hsscll << 8 | ( unsigned int ) fsscll;
+ sclh = ( unsigned int ) hssclh << 8 | ( unsigned int ) fssclh;
+
+ } else {
+ // Standard and fast speed
+ fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / ( 2 * speed );
+
+ fsscll -= I2C_FASTSPEED_SCLL_TRIM;
+ fssclh -= I2C_FASTSPEED_SCLH_TRIM;
+ if( ( ( fsscll < 0 ) || ( fssclh < 0 ) ) || ( ( fsscll > 255 ) ||
+ ( fssclh > 255 ) ) ) {
+ printk( "Error : I2C initializing clock\n" );
+ return;
+ }
+
+ scll = ( unsigned int ) fsscll;
+ sclh = ( unsigned int ) fssclh;
+ }
+
+ if( readw( &i2c_base->con ) & I2C_CON_EN ) {
+ writew( 0, &i2c_base->con );
+ udelay( 50000 );
+ }
+
+ writew( 0x2, &i2c_base->sysc ); /* for ES2 after soft reset */
+ udelay( 1000 );
+
+ writew( I2C_CON_EN, &i2c_base->con );
+ while( !( readw( &i2c_base->syss ) & I2C_SYSS_RDONE ) && timeout-- ) {
+ if (timeout <= 0) {
+ printk( "ERROR: Timeout in soft-reset\n" );
+ return;
+ }
+ udelay( 1000 );
+ }
+
+ writew( 0, &i2c_base->con );
+ writew( psc, &i2c_base->psc );
+ writew( scll, &i2c_base->scll );
+ writew( sclh, &i2c_base->sclh );
+
+ /* own address */
+ writew( slaveadd, &i2c_base->oa );
+ writew( I2C_CON_EN, &i2c_base->con );
+
+ /* have to enable intrrupts or OMAP i2c module doesn't work */
+ writew( I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE |
+ I2C_IE_AL_IE, &i2c_base->ie );
+ udelay( 1000 );
+ flush_fifo();
+ writew( 0xFFFF, &i2c_base->stat );
+ writew( 0, &i2c_base->cnt );
+
+ //if( gd->flags & GD_FLG_RELOC ) bus_initialized[ current_bus ] = 1;
+}
+
+static int i2c_read_byte(
+ unsigned char devaddr,
+ unsigned char regoffset,
+ unsigned char *value
+)
+{
+ int i2c_error = 0;
+ unsigned short status;
+
+ /* wait until bus not busy */
+ wait_for_bb();
+
+ /* one byte only */
+ writew(1, &i2c_base->cnt);
+ /* set slave address */
+ writew(devaddr, &i2c_base->sa);
+ /* no stop bit needed here */
+ writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
+ I2C_CON_TRX, &i2c_base->con);
+
+ /* send register offset */
+ while (1) {
+ status = wait_for_pin();
+ if (status == 0 || status & I2C_STAT_NACK) {
+ i2c_error = 1;
+ goto read_exit;
+ }
+ if (status & I2C_STAT_XRDY) {
+ /* Important: have to use byte access */
+ writeb(regoffset, &i2c_base->data);
+ writew(I2C_STAT_XRDY, &i2c_base->stat);
+ }
+ if (status & I2C_STAT_ARDY) {
+ writew(I2C_STAT_ARDY, &i2c_base->stat);
+ break;
+ }
+ }
+
+ /* set slave address */
+ writew(devaddr, &i2c_base->sa);
+ /* read one byte from slave */
+ writew(1, &i2c_base->cnt);
+ /* need stop bit here */
+ writew(I2C_CON_EN | I2C_CON_MST |
+ I2C_CON_STT | I2C_CON_STP,
+ &i2c_base->con);
+
+ /* receive data */
+ while (1) {
+ status = wait_for_pin();
+ if (status == 0 || status & I2C_STAT_NACK) {
+ i2c_error = 1;
+ goto read_exit;
+ }
+ if (status & I2C_STAT_RRDY) {
+ *value = readw(&i2c_base->data);
+ writew(I2C_STAT_RRDY, &i2c_base->stat);
+ }
+ if (status & I2C_STAT_ARDY) {
+ writew(I2C_STAT_ARDY, &i2c_base->stat);
+ break;
+ }
+ }
+
+read_exit:
+ flush_fifo();
+ writew(0xFFFF, &i2c_base->stat);
+ writew(0, &i2c_base->cnt);
+ return i2c_error;
+}
+
+int i2c_write(
+ unsigned char chip,
+ unsigned int addr,
+ int alen,
+ unsigned char *buffer,
+ int len
+)
+{
+ int i;
+ unsigned short status;
+ int i2c_error = 0;
+
+ if (alen > 1) {
+ printk("I2C write: addr len %d not supported\n", alen);
+ return 1;
+ }
+
+ if (addr + len > 256) {
+ printk("I2C write: address 0x%x + 0x%x out of range\n",
+ addr, len);
+ return 1;
+ }
+
+ /* wait until bus not busy */
+ wait_for_bb();
+
+ /* start address phase - will write regoffset + len bytes data */
+ writew(alen + len, &i2c_base->cnt);
+ /* set slave address */
+ writew(chip, &i2c_base->sa);
+ /* stop bit needed here */
+ writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
+ I2C_CON_STP, &i2c_base->con);
+
+ /* Send address byte */
+ status = wait_for_pin();
+
+ if (status == 0 || status & I2C_STAT_NACK) {
+ i2c_error = 1;
+ printk("error waiting for i2c address ACK (status=0x%x)\n",
+ status);
+ goto write_exit;
+ }
+
+ if (status & I2C_STAT_XRDY) {
+ writeb(addr & 0xFF, &i2c_base->data);
+ writew(I2C_STAT_XRDY, &i2c_base->stat);
+ } else {
+ i2c_error = 1;
+ printk("i2c bus not ready for transmit (status=0x%x)\n",
+ status);
+ goto write_exit;
+ }
+
+ /* address phase is over, now write data */
+ for (i = 0; i < len; i++) {
+ status = wait_for_pin();
+
+ if (status == 0 || status & I2C_STAT_NACK) {
+ i2c_error = 1;
+ printk("i2c error waiting for data ACK (status=0x%x)\n",
+ status);
+ goto write_exit;
+ }
+
+ if (status & I2C_STAT_XRDY) {
+ writeb(buffer[i], &i2c_base->data);
+ writew(I2C_STAT_XRDY, &i2c_base->stat);
+ } else {
+ i2c_error = 1;
+ printk("i2c bus not ready for Tx (i=%d)\n", i);
+ goto write_exit;
+ }
+ }
+
+write_exit:
+ flush_fifo();
+ writew(0xFFFF, &i2c_base->stat);
+ return i2c_error;
+}
+
+int i2c_read(
+ unsigned char chip,
+ uint addr,
+ int alen,
+ unsigned char *buffer,
+ int len
+)
+{
+ int i;
+
+ if (alen > 1) {
+ printk("I2C read: addr len %d not supported\n", alen);
+ return 1;
+ }
+
+ if (addr + len > 256) {
+ printk("I2C read: address out of range\n");
+ return 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_read_byte(chip, addr + i, &buffer[i])) {
+ printk("I2C read: I/O error\n");
+ i2c_init( CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE );
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Write (fill) memory
+ *
+ * Syntax:
+ * i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}]
+ */
+static int imw ( unsigned char chip, unsigned long addr, unsigned char byte )
+{
+
+ unsigned int alen;
+ int count;
+
+ alen = 1;
+ count = 1;
+
+ while (count-- > 0) {
+ if (i2c_write(chip, addr++, alen, &byte, 1) != 0)
+ printk("Error writing the chip.\n");
+ /*
+ * Wait for the write to complete. The write can take
+ * up to 10mSec (we allow a little more time).
+ */
+ }
+
+ return (0);
+}
+
+/*
+ * Syntax:
+ * i2c md {i2c_chip} {addr}{.0, .1, .2} {len}
+ */
+static int imd( unsigned char chip, unsigned int addr, unsigned int length )
+{
+ int j, nbytes, linebytes;
+
+ unsigned int alen = 0;
+ if (alen > 3) return 0;
+
+ /*
+ * Print the lines.
+ *
+ * We buffer all read data, so we can make sure data is read only
+ * once.
+ */
+ nbytes = length;
+ do {
+ unsigned char linebuf[DISP_LINE_LEN];
+ unsigned char *cp;
+
+ linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
+
+ if (i2c_read(chip, addr, alen, linebuf, linebytes) != 0)
+ printk ("Error reading the chip.\n");
+ else {
+ printk("%04x:", addr);
+ cp = linebuf;
+ for (j=0; j<linebytes; j++) {
+ printk(" %02x", *cp++);
+ addr++;
+ }
+ printk (" ");
+ cp = linebuf;
+ for (j=0; j<linebytes; j++) {
+ if ((*cp < 0x20) || (*cp > 0x7e))
+ printk (".");
+ else
+ printk("%c", *cp);
+ cp++;
+ }
+ printk ("\n");
+ }
+ nbytes -= linebytes;
+ } while (nbytes > 0);
+
+ return 0;
+}
diff --git a/c/src/lib/libbsp/arm/beagle/misc/restart.c b/c/src/lib/libbsp/arm/beagle/misc/restart.c
new file mode 100644
index 0000000000..fe7775ae06
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/misc/restart.c
@@ -0,0 +1,32 @@
+/**
+ * @file
+ *
+ * @ingroup beagle
+ *
+ * @brief Restart implementation.
+ */
+
+/*
+ * Copyright (c) 2012 Claas Ziemke. All rights reserved.
+ *
+ * Claas Ziemke
+ * Kernerstrasse 11
+ * 70182 Stuttgart
+ * Germany
+ * <claas.ziemke@gmx.net>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+#include <libcpu/arm-cp15.h>
+
+#include <bsp.h>
+
+void bsp_restart(void *addr)
+{
+ BEAGLE_DO_RESTART(addr);
+}
diff --git a/c/src/lib/libbsp/arm/beagle/misc/system-clocks.c b/c/src/lib/libbsp/arm/beagle/misc/system-clocks.c
new file mode 100644
index 0000000000..56b5d9aadb
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/misc/system-clocks.c
@@ -0,0 +1,140 @@
+/**
+ * @file
+ *
+ * @ingroup beagle
+ *
+ * @brief System clocks.
+ */
+
+/*
+ * Copyright (c) 2012 Claas Ziemke. All rights reserved.
+ *
+ * Claas Ziemke
+ * Kernerstrasse 11
+ * 70182 Stuttgart
+ * Germany
+ * <claas.ziemke@gmx.net>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/beagle.h>
+
+uint32_t beagle_sysclk(void)
+{
+ uint32_t sysclk_ctrl = BEAGLE_SYSCLK_CTRL;
+
+ return (sysclk_ctrl & 0x1) == 0 ?
+ BEAGLE_OSCILLATOR_MAIN
+ : (397 * BEAGLE_OSCILLATOR_RTC);
+}
+
+uint32_t beagle_hclkpll_clk(void)
+{
+ uint32_t sysclk = beagle_sysclk();
+ uint32_t hclkpll_ctrl = BEAGLE_HCLKPLL_CTRL;
+ uint32_t m = HCLK_PLL_M_GET(hclkpll_ctrl) + 1;
+ uint32_t n = HCLK_PLL_N_GET(hclkpll_ctrl) + 1;
+ uint32_t p = 1U << HCLK_PLL_P_GET(hclkpll_ctrl);
+ uint32_t hclkpll_clk = 0;
+
+ if ((hclkpll_ctrl & HCLK_PLL_BYPASS) != 0) {
+ if ((hclkpll_ctrl & HCLK_PLL_DIRECT) != 0) {
+ hclkpll_clk = sysclk;
+ } else {
+ hclkpll_clk = sysclk / (2 * p);
+ }
+ } else {
+ if ((hclkpll_ctrl & HCLK_PLL_DIRECT) != 0) {
+ hclkpll_clk = (m * sysclk) / n;
+ } else {
+ if ((hclkpll_ctrl & HCLK_PLL_FBD_FCLKOUT) != 0) {
+ hclkpll_clk = m * (sysclk / n);
+ } else {
+ hclkpll_clk = (m / (2 * p)) * (sysclk / n);
+ }
+ }
+ }
+
+ return hclkpll_clk;
+}
+
+uint32_t beagle_periph_clk(void)
+{
+ uint32_t pwr_ctrl = BEAGLE_PWR_CTRL;
+ uint32_t periph_clk = 0;
+
+ if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) != 0) {
+ uint32_t hclkdiv_ctrl = BEAGLE_HCLKDIV_CTRL;
+ uint32_t div = HCLK_DIV_PERIPH_CLK_GET(hclkdiv_ctrl) + 1;
+
+ periph_clk = beagle_hclkpll_clk() / div;
+ } else {
+ periph_clk = beagle_sysclk();
+ }
+
+ return periph_clk;
+}
+
+uint32_t beagle_hclk(void)
+{
+ uint32_t pwr_ctrl = BEAGLE_PWR_CTRL;
+ uint32_t hclk = 0;
+
+ if ((pwr_ctrl & PWR_HCLK_USES_PERIPH_CLK) != 0) {
+ hclk = beagle_periph_clk();
+ } else {
+ if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) != 0) {
+ uint32_t hclkdiv_ctrl = BEAGLE_HCLKDIV_CTRL;
+ uint32_t div = 1U << HCLK_DIV_HCLK_GET(hclkdiv_ctrl);
+
+ hclk = beagle_hclkpll_clk() / div;
+ } else {
+ hclk = beagle_sysclk();
+ }
+ }
+
+ return hclk;
+}
+
+uint32_t beagle_arm_clk(void)
+{
+ uint32_t pwr_ctrl = BEAGLE_PWR_CTRL;
+ uint32_t arm_clk = 0;
+
+ if ((pwr_ctrl & PWR_HCLK_USES_PERIPH_CLK) != 0) {
+ arm_clk = beagle_periph_clk();
+ } else {
+ if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) != 0) {
+ arm_clk = beagle_hclkpll_clk();
+ } else {
+ arm_clk = beagle_sysclk();
+ }
+ }
+
+ return arm_clk;
+}
+
+uint32_t beagle_dram_clk(void)
+{
+ uint32_t hclkdiv_ctrl = BEAGLE_HCLKDIV_CTRL;
+ uint32_t div = HCLK_DIV_DDRAM_CLK_GET(hclkdiv_ctrl);
+ uint32_t dram_clk = 0;
+
+ if (div != 0) {
+ uint32_t pwr_ctrl = BEAGLE_PWR_CTRL;
+
+ if ((pwr_ctrl & PWR_NORMAL_RUN_MODE) != 0) {
+ dram_clk = beagle_hclkpll_clk();
+ } else {
+ dram_clk = beagle_sysclk();
+ }
+
+ dram_clk /= div;
+ }
+
+ return dram_clk;
+}
diff --git a/c/src/lib/libbsp/arm/beagle/misc/timer.c b/c/src/lib/libbsp/arm/beagle/misc/timer.c
new file mode 100644
index 0000000000..50570e0b00
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/misc/timer.c
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup beagle
+ *
+ * @brief Benchmark timer support.
+ */
+
+/*
+ * Copyright (c) 2012 Claas Ziemke. All rights reserved.
+ *
+ * Claas Ziemke
+ * Kernerstrasse 11
+ * 70182 Stuttgart
+ * Germany
+ * <claas.ziemke@gmx.net>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <rtems/btimer.h>
+#include <rtems/timerdrv.h>
+
+#include <bsp.h>
+
+static uint32_t benchmark_timer_base;
+
+void benchmark_timer_initialize(void)
+{
+ benchmark_timer_base = beagleboard_timer();
+}
+
+uint32_t benchmark_timer_read(void)
+{
+ return beagleboard_timer() - benchmark_timer_base;
+}
+
+void benchmark_timer_disable_subtracting_average_overhead(
+ bool find_average_overhead
+)
+{
+ /* VOID */
+}