Index: kernel/arch/arm32/src/mach/beaglebone/beaglebone.c
===================================================================
--- kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2012 Matteo Facchinetti
+ * Copyright (c) 2012 Maurizio Lombardi
  * All rights reserved.
  *
@@ -38,4 +39,7 @@
 #include <genarch/drivers/am335x/uart.h>
 #include <genarch/drivers/am335x/timer.h>
+#include <genarch/drivers/am335x/cm_per.h>
+#include <genarch/drivers/am335x/cm_dpll.h>
+#include <genarch/drivers/am335x/ctrl_module.h>
 #include <genarch/srln/srln.h>
 #include <interrupt.h>
@@ -60,4 +64,7 @@
 static struct beaglebone {
 	am335x_irc_regs_t *irc_addr;
+	am335x_cm_per_regs_t *cm_per_addr;
+	am335x_cm_dpll_regs_t *cm_dpll_addr;
+	am335x_ctrl_module_t  *ctrl_module;
 	am335x_timer_t timer;
 	am335x_uart_t uart;
@@ -79,8 +86,17 @@
 static void bbone_init(void)
 {
-	/* Initialize the interrupt controller */
 	bbone.irc_addr = (void *) km_map(AM335x_IRC_BASE_ADDRESS,
 	    AM335x_IRC_SIZE, PAGE_NOT_CACHEABLE);
 
+	bbone.cm_per_addr = (void *) km_map(AM335x_CM_PER_BASE_ADDRESS,
+	    AM335x_CM_PER_SIZE, PAGE_NOT_CACHEABLE);
+
+	bbone.cm_dpll_addr = (void *) km_map(AM335x_CM_DPLL_BASE_ADDRESS,
+	    AM335x_CM_DPLL_SIZE, PAGE_NOT_CACHEABLE);
+
+	bbone.ctrl_module = (void *) km_map(AM335x_CTRL_MODULE_BASE_ADDRESS,
+	    AM335x_CTRL_MODULE_SIZE, PAGE_NOT_CACHEABLE);
+
+	/* Initialize the interrupt controller */
 	am335x_irc_init(bbone.irc_addr);
 }
@@ -105,13 +121,19 @@
 	irq_initialize(&timer_irq);
 	timer_irq.devno = device_assign_devno();
-	timer_irq.inr = AM335x_DMTIMER0_IRQ;
+	timer_irq.inr = AM335x_DMTIMER2_IRQ;
 	timer_irq.claim = bbone_timer_irq_claim;
 	timer_irq.handler = bbone_timer_irq_handler;
 	irq_register(&timer_irq);
 
-	/* Initialize the DMTIMER0 */
-	am335x_timer_init(&bbone.timer, DMTIMER0, HZ);
+	/* Enable the DMTIMER2 clock module */
+	am335x_clock_module_enable(bbone.cm_per_addr, DMTIMER2);
+	/* Select the SYSCLK as the clock source for the dmtimer2 module */
+	am335x_clock_source_select(bbone.cm_dpll_addr, DMTIMER2,
+	   CLK_SRC_M_OSC);
+	/* Initialize the DMTIMER2 */
+	am335x_timer_init(&bbone.timer, DMTIMER2, HZ,
+	    am335x_ctrl_module_clock_freq_get(bbone.ctrl_module));
 	/* Enable the interrupt */
-	am335x_irc_enable(bbone.irc_addr, AM335x_DMTIMER0_IRQ);
+	am335x_irc_enable(bbone.irc_addr, AM335x_DMTIMER2_IRQ);
 	/* Start the timer */
 	am335x_timer_start(&bbone.timer);
Index: kernel/genarch/include/drivers/am335x/cm_dpll.h
===================================================================
--- kernel/genarch/include/drivers/am335x/cm_dpll.h	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/genarch/include/drivers/am335x/cm_dpll.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -37,8 +37,40 @@
 #define _KERN_AM335X_CM_DPLL_H_
 
-#include <drivers/am335x/cm_dpll_regs.h>
+#include "cm_dpll_regs.h"
+#include "timer.h"
 
 #define AM335x_CM_DPLL_BASE_ADDRESS   0x44E00500
 #define AM335x_CM_DPLL_SIZE           256
+
+static ioport32_t *am335x_cm_dpll_timer_reg_get(am335x_cm_dpll_regs_t *cm,
+    am335x_timer_id_t id)
+{
+	switch (id) {
+	default:
+		return NULL;
+	case DMTIMER2:
+		return &cm->clksel_timer2;
+	case DMTIMER3:
+		return &cm->clksel_timer3;
+	case DMTIMER4:
+		return &cm->clksel_timer4;
+	case DMTIMER5:
+		return &cm->clksel_timer5;
+	case DMTIMER6:
+		return &cm->clksel_timer6;
+	case DMTIMER7:
+		return &cm->clksel_timer7;
+	}
+}
+
+static void am335x_clock_source_select(am335x_cm_dpll_regs_t *cm,
+    am335x_timer_id_t id, am335x_clk_src_t src)
+{
+	ioport32_t *reg = am335x_cm_dpll_timer_reg_get(cm, id);
+	if (!reg)
+		return;
+
+	*reg = (*reg & ~0x03) | src;
+}
 
 #endif
Index: kernel/genarch/include/drivers/am335x/cm_dpll_regs.h
===================================================================
--- kernel/genarch/include/drivers/am335x/cm_dpll_regs.h	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/genarch/include/drivers/am335x/cm_dpll_regs.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -37,7 +37,9 @@
 #define _KERN_AM335X_CM_DPLL_REGS_H_
 
-#define AM335x_CM_CLKSEL_TIMERS_CLK32KHZ    0x02
-#define AM335x_CM_CLKSEL_TIMERS_CLKMOSC     0x01
-#define AM335x_CM_CLKSEL_TIMERS_TCLKIN      0x00
+typedef enum {
+	CLK_SRC_TCLKIN = 0x00,
+	CLK_SRC_M_OSC,
+	CLK_SRC_32_KHZ
+} am335x_clk_src_t;
 
 typedef struct am335x_cm_dpll_regs {
@@ -76,5 +78,4 @@
 	ioport32_t clksel_gpio0_db;
 
-
 } am335x_cm_dpll_regs_t;
 
Index: kernel/genarch/include/drivers/am335x/cm_per.h
===================================================================
--- kernel/genarch/include/drivers/am335x/cm_per.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
+++ kernel/genarch/include/drivers/am335x/cm_per.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 Maurizio Lombardi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief Texas Instruments AM335x clock module.
+ */
+
+#ifndef _KERN_AM335X_CM_PER_H_
+#define _KERN_AM335X_CM_PER_H_
+
+#include <typedefs.h>
+#include "cm_per_regs.h"
+#include "timer.h"
+
+#define AM335x_CM_PER_BASE_ADDRESS   0x44E00000
+#define AM335x_CM_PER_SIZE           1024
+
+static ioport32_t *am335x_clock_clkctrl_reg_get(am335x_cm_per_regs_t *cm,
+    am335x_timer_id_t id)
+{
+	switch (id) {
+	default:
+		return NULL;
+	case DMTIMER2:
+		return &cm->timer2_clkctrl;
+	case DMTIMER3:
+		return &cm->timer3_clkctrl;
+	case DMTIMER4:
+		return &cm->timer4_clkctrl;
+	case DMTIMER5:
+		return &cm->timer5_clkctrl;
+	case DMTIMER6:
+		return &cm->timer6_clkctrl;
+	case DMTIMER7:
+		return &cm->timer7_clkctrl;
+	}
+
+}
+
+static void am335x_clock_module_enable(am335x_cm_per_regs_t *cm,
+    am335x_timer_id_t timer_id)
+{
+	ioport32_t *tmr_reg = am335x_clock_clkctrl_reg_get(cm, timer_id);
+	if (tmr_reg == NULL)
+		return;
+
+	/* Enable the clock module */
+	*tmr_reg = (*tmr_reg & ~0x03) | 0x02;
+
+	/* Wait for completion */
+	while ((*tmr_reg & 0x03) != 0x02);
+}
+
+#endif
+
+/**
+ * @}
+ */
+
Index: kernel/genarch/include/drivers/am335x/cm_per_regs.h
===================================================================
--- kernel/genarch/include/drivers/am335x/cm_per_regs.h	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/genarch/include/drivers/am335x/cm_per_regs.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -37,4 +37,6 @@
 #define _KERN_AM335X_CM_PER_REGS_H_
 
+#include <typedefs.h>
+
 typedef struct am335x_cm_per_regs {
 
@@ -145,5 +147,5 @@
 #define AM335x_CM_PER_MMC0_CLKCTRL_IDLEST_SHIFT     16
 
-	ioport32_ elm_clkctrl;
+	ioport32_t elm_clkctrl;
 #define AM335x_CM_PER_ELM_CLKCTRL_MODULEMODE_MASK  0x3
 #define AM335x_CM_PER_ELM_CLKCTRL_MODULEMODE_SHIFT 0
@@ -406,9 +408,9 @@
 	ioport32_t const pad7[2];
 
-	ioport32_t l3_clkstctrl;
-#define AM335x_CM_PER_L3_CLKSTCTRL_CLKTRCTRL_MASK     0x3
-#define AM335x_CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SHIFT    0
-#define AM335x_CM_PER_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_FLAG (1 << 4)
-#define AM335x_CM_PER_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_FLAG (1 << 5)
+	ioport32_t ocpwp_l3_clkstctrl;
+#define AM335x_CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_MASK     0x3
+#define AM335x_CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SHIFT    0
+#define AM335x_CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_FLAG (1 << 4)
+#define AM335x_CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_FLAG (1 << 5)
 
 	ioport32_t ocpwp_clkctrl;
Index: kernel/genarch/include/drivers/am335x/ctrl_module.h
===================================================================
--- kernel/genarch/include/drivers/am335x/ctrl_module.h	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/genarch/include/drivers/am335x/ctrl_module.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -37,16 +37,19 @@
 #define _KERN_AM335X_CTRL_MODULE_H_
 
-#include <drivers/am335x/ctrl_module_regs.h>
+#include <typedefs.h>
+#include "ctrl_module_regs.h"
 
 #define AM335x_CTRL_MODULE_BASE_ADDRESS  0x44E10000
 #define AM335x_CTRL_MODULE_SIZE          131072 /* 128 Kb */
 
-static unsigned am335x_ctrl_module_clock_freq_get(void *base)
+typedef ioport32_t am335x_ctrl_module_t;
+
+static unsigned am335x_ctrl_module_clock_freq_get(am335x_ctrl_module_t *base)
 {
-	unsigned const control_status = AM335x_CTRL_MODULE_REG_ADDR(base,
+	unsigned const control_status = *AM335x_CTRL_MODULE_REG_ADDR(base,
 	    CONTROL_SYSCONFIG);
 	unsigned const sysboot1 = (control_status >> 22) & 0x03;
 
-	switch (sysboot) {
+	switch (sysboot1) {
 	default:
 	case 0:
Index: kernel/genarch/include/drivers/am335x/timer.h
===================================================================
--- kernel/genarch/include/drivers/am335x/timer.h	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/genarch/include/drivers/am335x/timer.h	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -37,5 +37,5 @@
 #define _KERN_AM335X_TIMER_H_
 
-#include "timer_regs.h"
+#include <genarch/drivers/am335x/timer_regs.h>
 
 #define AM335x_DMTIMER0_BASE_ADDRESS    0x44E05000
@@ -86,5 +86,5 @@
 
 extern void am335x_timer_init(am335x_timer_t *timer, am335x_timer_id_t id,
-    unsigned hz);
+    unsigned hz, unsigned srcclk_hz);
 extern void am335x_timer_intr_ack(am335x_timer_t *timer);
 extern void am335x_timer_reset(am335x_timer_t *timer);
Index: kernel/genarch/src/drivers/am335x/timer.c
===================================================================
--- kernel/genarch/src/drivers/am335x/timer.c	(revision 40762c6f72f3b3c41b3ba8ee5303be204c4c6a8b)
+++ kernel/genarch/src/drivers/am335x/timer.c	(revision 4c754f62d3b72f6ad32d4e299d025db3a4c3f3f8)
@@ -56,5 +56,6 @@
 
 void
-am335x_timer_init(am335x_timer_t *timer, am335x_timer_id_t id, unsigned hz)
+am335x_timer_init(am335x_timer_t *timer, am335x_timer_id_t id, unsigned hz,
+    unsigned srcclk_hz)
 {
 	uintptr_t base_addr;
@@ -86,10 +87,8 @@
 	regs->tclr |= AM335x_TIMER_TCLR_AR_FLAG;
 
-	/* XXX Here we assume that the timer clock source
-	 * is running at 32 Khz but this is not always the
-	 * case; DMTIMER[2 - 7] can use the internal system 24 Mhz
-	 * clock source or an external clock also.
-	 */
-	unsigned const count = 0xFFFFFFFE - 32768 / hz;
+	/* Disable the emulation mode */
+	regs->tiocp_cfg |= AM335x_TIMER_TIOCPCFG_EMUFREE_FLAG;
+
+	unsigned const count = 0xFFFFFFFE - (srcclk_hz / hz);
 	regs->tcrr = count;
 	regs->tldr = count;
