From owner-svn-src-head@FreeBSD.ORG Mon May 21 04:24:59 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 9DFF41065670; Mon, 21 May 2012 04:24:59 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7E0C18FC0A; Mon, 21 May 2012 04:24:59 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4L4OxGV037061; Mon, 21 May 2012 04:24:59 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4L4Oxib037059; Mon, 21 May 2012 04:24:59 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201205210424.q4L4Oxib037059@svn.freebsd.org> From: Warner Losh Date: Mon, 21 May 2012 04:24:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235715 - head/sys/arm/at91 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 May 2012 04:24:59 -0000 Author: imp Date: Mon May 21 04:24:58 2012 New Revision: 235715 URL: http://svn.freebsd.org/changeset/base/235715 Log: Another minor re-arrangement of the code: calcualte the master clock frequency in the at91_pmc_clock_init rather than passing it in. Allow for frequencies >= 21MHz by rounding to the nearest 500Hz (Idea from Ian Lapore whose company uses a similar arrangement in their product). at91_pmc_clock_init() is now nearly independent of the rest of the pmc driver (which means we may be able to call it much earlier in boot soon to eliminate the master clock config file requirement for printf to work during early boot and also eliminate some interdependencies with the device ordering which requires pmc to be the first device added). Modified: head/sys/arm/at91/at91_pmc.c Modified: head/sys/arm/at91/at91_pmc.c ============================================================================== --- head/sys/arm/at91/at91_pmc.c Mon May 21 03:06:31 2012 (r235714) +++ head/sys/arm/at91/at91_pmc.c Mon May 21 04:24:58 2012 (r235715) @@ -388,12 +388,66 @@ fail: return (0); } +#if !defined(AT91C_MAIN_CLOCK) +static const unsigned int at91_main_clock_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 +}; +#define MAIN_CLOCK_TBL_LEN (sizeof(at91_main_clock_tbl) / sizeof(*at91_main_clock_tbl)) + +static unsigned int +at91_pmc_sense_main_clock(struct at91_pmc_softc *sc) +{ + unsigned int ckgr_val; + unsigned int diff, matchdiff, freq; + int i; + + ckgr_val = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11; + + /* + * Clocks up to 50MHz can be connected to some models. If + * the frequency is >= 21MHz, assume that the slow clock can + * measure it correctly, and that any error can be adequately + * compensated for by roudning to the nearest 500Hz. Users + * with fast, or odd-ball clocks will need to set + * AT91C_MASTER_CLOCK in the kernel config file. + */ + if (ckgr_val >= 21000000) + return ((ckgr_val + 250) / 500 * 500); + + /* + * Try to find the standard frequency that match best. + */ + freq = at91_main_clock_tbl[0]; + matchdiff = abs(ckgr_val - at91_main_clock_tbl[0]); + for (i = 1; i < MAIN_CLOCK_TBL_LEN; i++) { + diff = abs(ckgr_val - at91_main_clock_tbl[i]); + if (diff < matchdiff) { + freq = at91_main_clock_tbl[i]; + matchdiff = diff; + } + } + return (freq); +} +#endif + static void -at91_pmc_init_clock(struct at91_pmc_softc *sc, unsigned int main_clock) +at91_pmc_init_clock(struct at91_pmc_softc *sc) { + unsigned int main_clock; uint32_t mckr; uint32_t mdiv; +#if !defined(AT91C_MAIN_CLOCK) + main_clock = at91_pmc_sense_main_clock(pmc_softc); +#else + main_clock = AT91C_MAIN_CLOCK; +#endif + if (at91_is_sam9() || at91_is_sam9xe()) { uhpck.pmc_mask = PMC_SCER_UHP_SAM9; udpck.pmc_mask = PMC_SCER_UDP_SAM9; @@ -449,11 +503,9 @@ at91_pmc_init_clock(struct at91_pmc_soft at91_master_clock = mck.hz; - device_printf(sc->dev, - "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n", - main_clock, - plla.hz / 1000000, - cpu.hz / 1000000, mck.hz / 1000000); + /* These clocks refrenced by "special" names */ + at91_pmc_clock_alias("ohci0", "ohci_clk"); + at91_pmc_clock_alias("udp0", "udp_clk"); /* Turn off "Progamable" clocks */ WR4(sc, PMC_SCDR, PMC_SCER_PCK0 | PMC_SCER_PCK1 | PMC_SCER_PCK2 | @@ -505,46 +557,9 @@ at91_pmc_probe(device_t dev) return (0); } -#if !defined(AT91C_MAIN_CLOCK) -static const unsigned 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 -}; -#define MAINF_TBL_LEN (sizeof(at91_mainf_tbl) / sizeof(*at91_mainf_tbl)) - -static unsigned int -at91_pmc_sense_mainf(struct at91_pmc_softc *sc) -{ - unsigned int ckgr_val; - unsigned int diff, matchdiff; - int i, match; - - ckgr_val = (RD4(sc, CKGR_MCFR) & CKGR_MCFR_MAINF_MASK) << 11; - - /* - * Try to find the standard frequency that match best. - */ - match = 0; - matchdiff = abs(ckgr_val - at91_mainf_tbl[0]); - for (i = 1; i < MAINF_TBL_LEN; i++) { - diff = abs(ckgr_val - at91_mainf_tbl[i]); - if (diff < matchdiff) { - match = i; - matchdiff = diff; - } - } - return (at91_mainf_tbl[match]); -} -#endif - static int at91_pmc_attach(device_t dev) { - unsigned int mainf; int err; pmc_softc = device_get_softc(dev); @@ -555,16 +570,13 @@ at91_pmc_attach(device_t dev) /* * Configure main clock frequency. */ -#if !defined(AT91C_MAIN_CLOCK) - mainf = at91_pmc_sense_mainf(pmc_softc); -#else - mainf = AT91C_MAIN_CLOCK; -#endif - at91_pmc_init_clock(pmc_softc, mainf); + at91_pmc_init_clock(pmc_softc); - /* These clocks refrenced by "special" names */ - at91_pmc_clock_alias("ohci0", "ohci_clk"); - at91_pmc_clock_alias("udp0", "udp_clk"); + device_printf(dev, + "Primary: %d Hz PLLA: %d MHz CPU: %d MHz MCK: %d MHz\n", + main_ck.hz, + plla.hz / 1000000, + cpu.hz / 1000000, mck.hz / 1000000); return (0); }