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;
