summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorJasper Lievisse Adriaanse <jasper@cvs.openbsd.org>2011-03-14 15:16:47 +0000
committerJasper Lievisse Adriaanse <jasper@cvs.openbsd.org>2011-03-14 15:16:47 +0000
commitb33ab19ac337857f8d07e39d5854e08e80aa9f0a (patch)
tree348d9bad50c1650f4e978518e5847e8317779bda /sys/arch
parent05c5064fde2a319b6f4b74f8226fd0dc8b619711 (diff)
use DPLL5 as a 120MHz reference clock to be used by the usb subsystem which
previously had no clue and would crash. feedback/ok drahn@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/beagle/dev/prcm.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/sys/arch/beagle/dev/prcm.c b/sys/arch/beagle/dev/prcm.c
index 04fd63c7cf9..6fb56f36487 100644
--- a/sys/arch/beagle/dev/prcm.c
+++ b/sys/arch/beagle/dev/prcm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: prcm.c,v 1.4 2010/08/07 03:50:01 krw Exp $ */
+/* $OpenBSD: prcm.c,v 1.5 2011/03/14 15:16:46 jasper Exp $ */
/*
* Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
*
@@ -15,6 +15,10 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Driver for the Power, Reset and Clock Management Module (PRCM).
+ */
+
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -106,10 +110,15 @@
#define PM_WKEN_WKUP 0x0cA0
#define PM_WKST_WKUP 0x0cB0
#define CM_CLKEN_PLL 0x0d00
+#define CM_CLKEN2_PLL 0x0d04
#define CM_IDLEST_CKGEN 0x0d20
#define CM_AUTOIDLE_PLL 0x0d30
+#define CM_AUTOIDLE2_PLL 0x0d34
#define CM_CLKSEL1_PLL 0x0d40
#define CM_CLKSEL2_PLL 0x0d44
+#define CM_CLKSEL3_PLL 0x0d48
+#define CM_CLKSEL4_PLL 0x0d4C
+#define CM_CLKSEL5_PLL 0x0d50
#define CM_FCLKEN_PER 0x1000
#define CM_ICLKEN_PER 0x1010
#define CM_IDLEST_PER 0x1020
@@ -147,14 +156,15 @@ uint32_t prcm_fmask_addr[PRCM_REG_MAX];
#define PRCM_SIZE 0x2000
-bus_space_tag_t prcm_iot;
-bus_space_handle_t prcm_ioh;
+#define SYS_CLK 13 /* SYS_CLK speed in MHz */
+
+bus_space_tag_t prcm_iot;
+bus_space_handle_t prcm_ioh;
int prcm_attached;
int prcm_match(struct device *, void *, void *);
void prcm_attach(struct device *, struct device *, void *);
-
-
+int prcm_setup_dpll5(void);
struct cfattach prcm_ca = {
sizeof (struct device), prcm_match, prcm_attach
@@ -188,6 +198,9 @@ prcm_attach(struct device *parent, struct device *self, void *args)
prcm_attached = 1;
+ /* Setup the 120MHZ DPLL5 clock, to be used by USB. */
+ prcm_setup_dpll5();
+
/* XXX */
#if 1
printf("CM_FCLKEN1_CORE %x\n", bus_space_read_4(prcm_iot, prcm_ioh, CM_FCLKEN1_CORE));
@@ -296,3 +309,49 @@ prcm_enableclock(int bit)
}
printf ("\n");
}
+
+/*
+ * OMAP35xx Power, Reset, and Clock Management Reference Guide
+ * (sprufa5.pdf) and AM/DM37x Multimedia Device Technical Reference
+ * Manual (sprugn4h.pdf) note that DPLL5 provides a 120MHz clock for
+ * peripheral domain modules (page 107 and page 302).
+ * The reference clock for DPLL5 is DPLL5_ALWON_FCLK which is
+ * SYS_CLK, running at 13MHz.
+ */
+int
+prcm_setup_dpll5(void)
+{
+ uint32_t val;
+
+ /*
+ * We need to set the multiplier and divider values for PLL.
+ * To end up with 120MHz we take SYS_CLK, divide by it and multiply
+ * with 120 (sprugn4h.pdf, 13.4.11.4.1 SSC Configuration)
+ */
+ val = ((120 & 0x7ff) << 8) | ((SYS_CLK - 1) & 0x7f);
+ bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL4_PLL, val);
+
+ /* Clock divider from the PLL to the 120MHz clock. */
+ bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKSEL5_PLL, val);
+
+ /*
+ * spruf98o.pdf, page 2319:
+ * PERIPH2_DPLL_FREQSEL is 0x7 1.75MHz to 2.1MHz
+ * EN_PERIPH2_DPLL is 0x7
+ */
+ val = (7 << 4) | (7 << 0);
+ bus_space_write_4(prcm_iot, prcm_ioh, CM_CLKEN2_PLL, val);
+
+ /* Disable the interconnect clock auto-idle. */
+ bus_space_write_4(prcm_iot, prcm_ioh, CM_AUTOIDLE2_PLL, 0x0);
+
+ /* Wait until DPLL5 is locked and there's clock activity. */
+ while ((val = bus_space_read_4(prcm_iot, prcm_ioh,
+ CM_IDLEST_CKGEN) & 0x01) == 0x00) {
+#ifdef DIAGNOSTIC
+ printf("CM_IDLEST_PLL = 0x&08x\n", val);
+#endif
+ }
+
+ return 0;
+}