arm/128961: [patch] Detect main clock frequency of AT91 controller.
Björn König
bkoenig at alpha-tierchen.de
Tue Nov 18 04:10:06 PST 2008
>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:
More information about the freebsd-arm
mailing list