Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Nov 2008 13:03:35 +0100 (CET)
From:      Björn König <bkoenig@alpha-tierchen.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   arm/128961: [patch] Detect main clock frequency of AT91 controller.
Message-ID:  <20081118120335.363CE28A19@home.alpha-tierchen.de>
Resent-Message-ID: <200811181210.mAICA6sl043677@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         128961
>Category:       arm
>Synopsis:       [patch] Detect main clock frequency of AT91 controller.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-arm
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 18 12:10:06 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Björn König
>Release:        
>Organization:
>Environment:

>Description:
	The PMC of the AT91 controller provides a register
	where you can find an estimation of the main clock
	frequency. The patch below uses this register to
	sense the frequency of the oscillating crystal.

	Alternatively you can set the frequency explicitely
	in the kernel configuration file with

	options AT91C_MAIN_CLOCK=16000000

	for example.

>How-To-Repeat:
	
>Fix:

	

--- src-sys-arm-at91.diff begins here ---
diff --git src/sys/arm/at91/at91_pmc.c src/sys/arm/at91/at91_pmc.c
index 061e2bc..c2a97ab 100644
--- src/sys/arm/at91/at91_pmc.c
+++ src/sys/arm/at91/at91_pmc.c
@@ -144,6 +144,17 @@ static struct at91_pmc_clock *const clock_list[] = {
 	&ohci_clk
 };
 
+#if !defined(AT91C_MAIN_CLOCK)
+static const int at91_mainf_tbl[] = {
+	 3000000,  3276800,  3686400,  3840000,  4000000,
+	 4433619,  4915200,  5000000,  5242880,  6000000,
+	 6144000,  6400000,  6553600,  7159090,  7372800,
+	 7864320,  8000000,  9830400, 10000000, 11059200,
+	12000000, 12288000, 13560000, 14318180, 14745600,
+	16000000, 17344700, 18432000, 20000000, 0
+};
+#endif
+
 static inline uint32_t
 RD4(struct at91_pmc_softc *sc, bus_size_t off)
 {
@@ -383,6 +394,26 @@ at91_pmc_probe(device_t dev)
 	return (0);
 }
 
+#if !defined(AT91C_MAIN_CLOCK)
+static int
+at91_pmc_sense_mainf(struct at91_pmc_softc *sc)
+{
+	int ret = 0;
+	const int *p;
+	int mainf = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11;
+	unsigned diff = (unsigned)-1;
+
+	for (p = at91_mainf_tbl; *p != 0; p++)
+		if (abs(mainf - *p) < diff)
+		{
+			diff = abs(mainf - *p);
+			ret = *p;
+		}
+
+	return (ret);
+}
+#endif
+
 static int
 at91_pmc_attach(device_t dev)
 {
@@ -392,10 +423,10 @@ at91_pmc_attach(device_t dev)
 	pmc_softc->dev = dev;
 	if ((err = at91_pmc_activate(dev)) != 0)
 		return err;
-#if defined(AT91_TSC) | defined (AT91_BWCT)
-	at91_pmc_init_clock(pmc_softc, 16000000);
+#if defined(AT91C_MAIN_CLOCK)
+	at91_pmc_init_clock(pmc_softc, AT91C_MAIN_CLOCK);
 #else
-	at91_pmc_init_clock(pmc_softc, 10000000);
+	at91_pmc_init_clock(pmc_softc, at91_pmc_sense_mainf(pmc_softc));
 #endif
 
 	return (0);
diff --git src/sys/conf/options.arm src/sys/conf/options.arm
index 66b2575..56791a8 100644
--- src/sys/conf/options.arm
+++ src/sys/conf/options.arm
@@ -5,6 +5,7 @@ ARMFPE			opt_global.h
 ARM_KERN_DIRECTMAP	opt_vm.h
 ARM_USE_SMALL_ALLOC	opt_global.h
 AT91C_MASTER_CLOCK	opt_global.h
+AT91C_MAIN_CLOCK	opt_at91.h
 COUNTS_PER_SEC		opt_timer.h
 CPU_SA1100		opt_global.h
 CPU_SA1110		opt_global.h
--- src-sys-arm-at91.diff ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20081118120335.363CE28A19>