From patchwork Tue Jun 7 23:27:57 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andreas_Bie=C3=9Fmann?= X-Patchwork-Id: 99344 X-Patchwork-Delegate: info@emk-elektronik.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 1627BB6FA9 for ; Wed, 8 Jun 2011 09:28:39 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 68F652825D; Wed, 8 Jun 2011 01:28:31 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zylCf6GyuapS; Wed, 8 Jun 2011 01:28:31 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D855D28274; Wed, 8 Jun 2011 01:28:26 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 68676280EF for ; Wed, 8 Jun 2011 01:28:16 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nQG7et54hrxm for ; Wed, 8 Jun 2011 01:28:13 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-bw0-f44.google.com (mail-bw0-f44.google.com [209.85.214.44]) by theia.denx.de (Postfix) with ESMTPS id 0CBD6282FB for ; Wed, 8 Jun 2011 01:28:11 +0200 (CEST) Received: by bwz13 with SMTP id 13so200266bwz.3 for ; Tue, 07 Jun 2011 16:28:11 -0700 (PDT) Received: by 10.204.20.134 with SMTP id f6mr534394bkb.165.1307489291296; Tue, 07 Jun 2011 16:28:11 -0700 (PDT) Received: from andreas-mbp.erlangen.biessmann.tld (dslb-188-105-233-069.pools.arcor-ip.net [188.105.233.69]) by mx.google.com with ESMTPS id ek1sm12483bkb.9.2011.06.07.16.28.09 (version=SSLv3 cipher=OTHER); Tue, 07 Jun 2011 16:28:10 -0700 (PDT) From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= To: u-boot@lists.denx.de, Reinhard Meyer Date: Wed, 8 Jun 2011 01:27:57 +0200 Message-Id: <1307489278-96804-2-git-send-email-andreas.devel@googlemail.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1307489278-96804-1-git-send-email-andreas.devel@googlemail.com> References: <1307489278-96804-1-git-send-email-andreas.devel@googlemail.com> MIME-Version: 1.0 Subject: [U-Boot] [PATCH 1/2] at91: move a/a/c/arm926ejs/at91/clock.c -> a/a/lib/at91 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de The at91/clock.c is copied from linux kernel and has support for both arm920t and arm926ejs core devices. Therefore this patch moves this generic at91/clock.c to a new place at arch/arm/lib/at91 to be used from at91 family devices. We build a new libat91-common.o to provide the required symbols to both cpu types. Signed-off-by: Andreas Bießmann --- Makefile | 3 + arch/arm/cpu/arm926ejs/at91/Makefile | 1 - arch/arm/cpu/arm926ejs/at91/clock.c | 215 ---------------------------------- arch/arm/lib/at91/Makefile | 45 +++++++ arch/arm/lib/at91/clock.c | 215 ++++++++++++++++++++++++++++++++++ 5 files changed, 263 insertions(+), 216 deletions(-) delete mode 100644 arch/arm/cpu/arm926ejs/at91/clock.c create mode 100644 arch/arm/lib/at91/Makefile create mode 100644 arch/arm/lib/at91/clock.c diff --git a/Makefile b/Makefile index 76124e5..64e47c7 100644 --- a/Makefile +++ b/Makefile @@ -189,6 +189,9 @@ LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \ LIBS += $(CPUDIR)/lib$(CPU).o ifdef SOC LIBS += $(CPUDIR)/$(SOC)/lib$(SOC).o +ifeq ($(SOC),at91) +LIBS += arch/arm/lib/at91/libat91-common.o +endif endif ifeq ($(CPU),ixp) LIBS += arch/arm/cpu/ixp/npe/libnpe.o diff --git a/arch/arm/cpu/arm926ejs/at91/Makefile b/arch/arm/cpu/arm926ejs/at91/Makefile index f333753..ee66b3d 100644 --- a/arch/arm/cpu/arm926ejs/at91/Makefile +++ b/arch/arm/cpu/arm926ejs/at91/Makefile @@ -37,7 +37,6 @@ COBJS-$(CONFIG_AT91SAM9M10G45) += at91sam9m10g45_devices.o COBJS-$(CONFIG_AT91SAM9G45) += at91sam9m10g45_devices.o COBJS-$(CONFIG_AT91_EFLASH) += eflash.o COBJS-$(CONFIG_AT91_LED) += led.o -COBJS-y += clock.o COBJS-y += cpu.o COBJS-y += reset.o COBJS-y += timer.o diff --git a/arch/arm/cpu/arm926ejs/at91/clock.c b/arch/arm/cpu/arm926ejs/at91/clock.c deleted file mode 100644 index 608af2c..0000000 --- a/arch/arm/cpu/arm926ejs/at91/clock.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] - * - * Copyright (C) 2005 David Brownell - * Copyright (C) 2005 Ivan Kokshaysky - * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#if !defined(CONFIG_AT91FAMILY) -# error You need to define CONFIG_AT91FAMILY in your board config! -#endif - -DECLARE_GLOBAL_DATA_PTR; - -unsigned long get_cpu_clk_rate(void) -{ - return gd->cpu_clk_rate_hz; -} - -unsigned long get_main_clk_rate(void) -{ - return gd->main_clk_rate_hz; -} - -unsigned long get_mck_clk_rate(void) -{ - return gd->mck_rate_hz; -} - -unsigned long get_plla_clk_rate(void) -{ - return gd->plla_rate_hz; -} - -unsigned long get_pllb_clk_rate(void) -{ - return gd->pllb_rate_hz; -} - -u32 get_pllb_init(void) -{ - return gd->at91_pllb_usb_init; -} - -static unsigned long at91_css_to_rate(unsigned long css) -{ - switch (css) { - case AT91_PMC_MCKR_CSS_SLOW: - return CONFIG_SYS_AT91_SLOW_CLOCK; - case AT91_PMC_MCKR_CSS_MAIN: - return gd->main_clk_rate_hz; - case AT91_PMC_MCKR_CSS_PLLA: - return gd->plla_rate_hz; - case AT91_PMC_MCKR_CSS_PLLB: - return gd->pllb_rate_hz; - } - - return 0; -} - -#ifdef CONFIG_USB_ATMEL -static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq) -{ - unsigned i, div = 0, mul = 0, diff = 1 << 30; - unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; - - /* PLL output max 240 MHz (or 180 MHz per errata) */ - if (out_freq > 240000000) - goto fail; - - for (i = 1; i < 256; i++) { - int diff1; - unsigned input, mul1; - - /* - * PLL input between 1MHz and 32MHz per spec, but lower - * frequences seem necessary in some cases so allow 100K. - * Warning: some newer products need 2MHz min. - */ - input = main_freq / i; -#if defined(CONFIG_AT91SAM9G20) - if (input < 2000000) - continue; -#endif - if (input < 100000) - continue; - if (input > 32000000) - continue; - - mul1 = out_freq / input; -#if defined(CONFIG_AT91SAM9G20) - if (mul > 63) - continue; -#endif - if (mul1 > 2048) - continue; - if (mul1 < 2) - goto fail; - - diff1 = out_freq - input * mul1; - if (diff1 < 0) - diff1 = -diff1; - if (diff > diff1) { - diff = diff1; - div = i; - mul = mul1; - if (diff == 0) - break; - } - } - if (i == 256 && diff > (out_freq >> 5)) - goto fail; - return ret | ((mul - 1) << 16) | div; -fail: - return 0; -} -#endif - -static u32 at91_pll_rate(u32 freq, u32 reg) -{ - unsigned mul, div; - - div = reg & 0xff; - mul = (reg >> 16) & 0x7ff; - if (div && mul) { - freq /= div; - freq *= mul + 1; - } else - freq = 0; - - return freq; -} - -int at91_clock_init(unsigned long main_clock) -{ - unsigned freq, mckr; - at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; -#ifndef CONFIG_SYS_AT91_MAIN_CLOCK - unsigned tmp; - /* - * When the bootloader initialized the main oscillator correctly, - * there's no problem using the cycle counter. But if it didn't, - * or when using oscillator bypass mode, we must be told the speed - * of the main clock. - */ - if (!main_clock) { - do { - tmp = readl(&pmc->mcfr); - } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); - tmp &= AT91_PMC_MCFR_MAINF_MASK; - main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); - } -#endif - gd->main_clk_rate_hz = main_clock; - - /* report if PLLA is more than mildly overclocked */ - gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); - -#ifdef CONFIG_USB_ATMEL - /* - * USB clock init: choose 48 MHz PLLB value, - * disable 48MHz clock during usb peripheral suspend. - * - * REVISIT: assumes MCK doesn't derive from PLLB! - */ - gd->at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | - AT91_PMC_PLLBR_USBDIV_2; - gd->pllb_rate_hz = at91_pll_rate(main_clock, gd->at91_pllb_usb_init); -#endif - - /* - * MCK and CPU derive from one of those primary clocks. - * For now, assume this parentage won't change. - */ - mckr = readl(&pmc->mckr); -#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) - /* plla divisor by 2 */ - gd->plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12)); -#endif - gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); - freq = gd->mck_rate_hz; - - freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ -#if defined(CONFIG_AT91RM9200) - /* mdiv */ - gd->mck_rate_hz = freq / (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); -#elif defined(CONFIG_AT91SAM9G20) - /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ - gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ? - freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq; - if (mckr & AT91_PMC_MCKR_MDIV_MASK) - freq /= 2; /* processor clock division */ -#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) - gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) == - (AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4) - ? freq / 3 - : freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); -#else - gd->mck_rate_hz = freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); -#endif - gd->cpu_clk_rate_hz = freq; - - return 0; -} diff --git a/arch/arm/lib/at91/Makefile b/arch/arm/lib/at91/Makefile new file mode 100644 index 0000000..a264630 --- /dev/null +++ b/arch/arm/lib/at91/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2000-2008 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)libat91-common.o + +COBJS-y += clock.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/lib/at91/clock.c b/arch/arm/lib/at91/clock.c new file mode 100644 index 0000000..608af2c --- /dev/null +++ b/arch/arm/lib/at91/clock.c @@ -0,0 +1,215 @@ +/* + * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long get_cpu_clk_rate(void) +{ + return gd->cpu_clk_rate_hz; +} + +unsigned long get_main_clk_rate(void) +{ + return gd->main_clk_rate_hz; +} + +unsigned long get_mck_clk_rate(void) +{ + return gd->mck_rate_hz; +} + +unsigned long get_plla_clk_rate(void) +{ + return gd->plla_rate_hz; +} + +unsigned long get_pllb_clk_rate(void) +{ + return gd->pllb_rate_hz; +} + +u32 get_pllb_init(void) +{ + return gd->at91_pllb_usb_init; +} + +static unsigned long at91_css_to_rate(unsigned long css) +{ + switch (css) { + case AT91_PMC_MCKR_CSS_SLOW: + return CONFIG_SYS_AT91_SLOW_CLOCK; + case AT91_PMC_MCKR_CSS_MAIN: + return gd->main_clk_rate_hz; + case AT91_PMC_MCKR_CSS_PLLA: + return gd->plla_rate_hz; + case AT91_PMC_MCKR_CSS_PLLB: + return gd->pllb_rate_hz; + } + + return 0; +} + +#ifdef CONFIG_USB_ATMEL +static unsigned at91_pll_calc(unsigned main_freq, unsigned out_freq) +{ + unsigned i, div = 0, mul = 0, diff = 1 << 30; + unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00; + + /* PLL output max 240 MHz (or 180 MHz per errata) */ + if (out_freq > 240000000) + goto fail; + + for (i = 1; i < 256; i++) { + int diff1; + unsigned input, mul1; + + /* + * PLL input between 1MHz and 32MHz per spec, but lower + * frequences seem necessary in some cases so allow 100K. + * Warning: some newer products need 2MHz min. + */ + input = main_freq / i; +#if defined(CONFIG_AT91SAM9G20) + if (input < 2000000) + continue; +#endif + if (input < 100000) + continue; + if (input > 32000000) + continue; + + mul1 = out_freq / input; +#if defined(CONFIG_AT91SAM9G20) + if (mul > 63) + continue; +#endif + if (mul1 > 2048) + continue; + if (mul1 < 2) + goto fail; + + diff1 = out_freq - input * mul1; + if (diff1 < 0) + diff1 = -diff1; + if (diff > diff1) { + diff = diff1; + div = i; + mul = mul1; + if (diff == 0) + break; + } + } + if (i == 256 && diff > (out_freq >> 5)) + goto fail; + return ret | ((mul - 1) << 16) | div; +fail: + return 0; +} +#endif + +static u32 at91_pll_rate(u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 16) & 0x7ff; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else + freq = 0; + + return freq; +} + +int at91_clock_init(unsigned long main_clock) +{ + unsigned freq, mckr; + at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK + unsigned tmp; + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = readl(&pmc->mcfr); + } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); + tmp &= AT91_PMC_MCFR_MAINF_MASK; + main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); + } +#endif + gd->main_clk_rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + gd->plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); + +#ifdef CONFIG_USB_ATMEL + /* + * USB clock init: choose 48 MHz PLLB value, + * disable 48MHz clock during usb peripheral suspend. + * + * REVISIT: assumes MCK doesn't derive from PLLB! + */ + gd->at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | + AT91_PMC_PLLBR_USBDIV_2; + gd->pllb_rate_hz = at91_pll_rate(main_clock, gd->at91_pllb_usb_init); +#endif + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = readl(&pmc->mckr); +#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) + /* plla divisor by 2 */ + gd->plla_rate_hz /= (1 << ((mckr & 1 << 12) >> 12)); +#endif + gd->mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); + freq = gd->mck_rate_hz; + + freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ +#if defined(CONFIG_AT91RM9200) + /* mdiv */ + gd->mck_rate_hz = freq / (1 + ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); +#elif defined(CONFIG_AT91SAM9G20) + /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ + gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ? + freq / ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 7) : freq; + if (mckr & AT91_PMC_MCKR_MDIV_MASK) + freq /= 2; /* processor clock division */ +#elif defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) + gd->mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) == + (AT91_PMC_MCKR_MDIV_2 | AT91_PMC_MCKR_MDIV_4) + ? freq / 3 + : freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); +#else + gd->mck_rate_hz = freq / (1 << ((mckr & AT91_PMC_MCKR_MDIV_MASK) >> 8)); +#endif + gd->cpu_clk_rate_hz = freq; + + return 0; +}