From patchwork Sun Jul 21 21:51:55 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukasz Majewski X-Patchwork-Id: 260554 X-Patchwork-Delegate: promsoft@gmail.com 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 8E6C72C00A3 for ; Mon, 22 Jul 2013 10:22:02 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 119504A04E; Mon, 22 Jul 2013 02:22:00 +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 dV79OXiUZu6j; Mon, 22 Jul 2013 02:21:59 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9105E4A03C; Mon, 22 Jul 2013 02:21:55 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BB10A4A03C for ; Mon, 22 Jul 2013 02:21:49 +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 bnmO2K8mK5At for ; Mon, 22 Jul 2013 02:21:43 +0200 (CEST) X-Greylist: delayed 8970 seconds by postgrey-1.27 at theia; Mon, 22 Jul 2013 02:21:38 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 mo2.mail-out.ovh.net (mo2.mail-out.ovh.net [178.32.228.2]) by theia.denx.de (Postfix) with ESMTP id 653884A03B for ; Mon, 22 Jul 2013 02:21:37 +0200 (CEST) Received: from mail21.ha.ovh.net (b6.ovh.net [213.186.33.56]) by mo2.mail-out.ovh.net (Postfix) with SMTP id 21307DC37ED for ; Sun, 21 Jul 2013 23:52:07 +0200 (CEST) Received: from b0.ovh.net (HELO queueout) (213.186.33.50) by b0.ovh.net with SMTP; 21 Jul 2013 23:52:06 +0200 Received: from 178235168002.warszawa.vectranet.pl (HELO localhost.localdomain) (l.majewski%majess.pl@178.235.168.2) by ns0.ovh.net with SMTP; 21 Jul 2013 23:52:03 +0200 From: Lukasz Majewski To: u-boot@lists.denx.de X-Ovh-Mailout: 178.32.228.2 (mo2.mail-out.ovh.net) Date: Sun, 21 Jul 2013 23:51:55 +0200 Message-Id: <1374443515-11152-1-git-send-email-l.majewski@majess.pl> X-Mailer: git-send-email 1.7.10.4 X-Ovh-Tracer-Id: 6341912701953622554 X-Ovh-Remote: 178.235.168.2 (178235168002.warszawa.vectranet.pl) X-Ovh-Local: 213.186.33.20 (ns0.ovh.net) X-OVH-SPAMSTATE: OK X-OVH-SPAMSCORE: -100 X-OVH-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeeijedrfedtucetufdoteggodetrfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-Spam-Check: DONE|U 0.5/N X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeeijedrfeduucetufdoteggodetrfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd Cc: Tomasz Figa , Rajeshwari Shinde Subject: [U-Boot] [PATCH] arm:samsung:timer: Move common timer related code to ./samsung-common/ directory X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Common Samsung's timer/pwm code has been moved one level up - to ./samsung-common directory. This would allow other - non S5P based targets to reuse it. As a side effect, duplicated header files have been removed. Signed-off-by: Lukasz Majewski Cc: Minkyu Kang --- Makefile | 7 +- arch/arm/cpu/armv7/s5p-common/Makefile | 2 - arch/arm/cpu/armv7/s5p-common/pwm.c | 187 ---------------------------- arch/arm/cpu/armv7/s5p-common/timer.c | 148 ----------------------- arch/arm/cpu/samsung-common/Makefile | 48 ++++++++ arch/arm/cpu/samsung-common/pwm.c | 188 +++++++++++++++++++++++++++++ arch/arm/cpu/samsung-common/timer.c | 149 +++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/pwm.h | 68 ----------- arch/arm/include/asm/arch-s5pc1xx/pwm.h | 68 ----------- arch/arm/include/asm/samsung-common/pwm.h | 68 +++++++++++ 10 files changed, 457 insertions(+), 476 deletions(-) delete mode 100644 arch/arm/cpu/armv7/s5p-common/pwm.c delete mode 100644 arch/arm/cpu/armv7/s5p-common/timer.c create mode 100644 arch/arm/cpu/samsung-common/Makefile create mode 100644 arch/arm/cpu/samsung-common/pwm.c create mode 100644 arch/arm/cpu/samsung-common/timer.c delete mode 100644 arch/arm/include/asm/arch-exynos/pwm.h delete mode 100644 arch/arm/include/asm/arch-s5pc1xx/pwm.h create mode 100644 arch/arm/include/asm/samsung-common/pwm.h diff --git a/Makefile b/Makefile index f100b83..d53ccd2 100644 --- a/Makefile +++ b/Makefile @@ -346,12 +346,13 @@ ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx31 mx35 mxs vf610)) LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o endif -ifeq ($(SOC),s5pc1xx) +ifeq ($(CPU),armv7) +LIBS-y += arch/$(ARCH)/cpu/samsung-common/libsamsung-common.o +ifneq (,$(filter $(SOC), exynos s5pc1xx)) LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o endif -ifeq ($(SOC),exynos) -LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o endif + ifneq ($(CONFIG_TEGRA),) LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile index 0c38bd0..e48ecd7 100644 --- a/arch/arm/cpu/armv7/s5p-common/Makefile +++ b/arch/arm/cpu/armv7/s5p-common/Makefile @@ -27,9 +27,7 @@ LIB = $(obj)libs5p-common.o COBJS-y += cpu_info.o ifndef CONFIG_SPL_BUILD -COBJS-y += timer.o COBJS-y += sromc.o -COBJS-$(CONFIG_PWM) += pwm.o endif SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c deleted file mode 100644 index 6f401b8..0000000 --- a/arch/arm/cpu/armv7/s5p-common/pwm.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * - * Donghwa Lee - * - * 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 -#include -#include -#include -#include -#include - -int pwm_enable(int pwm_id) -{ - const struct s5p_timer *pwm = - (struct s5p_timer *)samsung_get_base_timer(); - unsigned long tcon; - - tcon = readl(&pwm->tcon); - tcon |= TCON_START(pwm_id); - - writel(tcon, &pwm->tcon); - - return 0; -} - -void pwm_disable(int pwm_id) -{ - const struct s5p_timer *pwm = - (struct s5p_timer *)samsung_get_base_timer(); - unsigned long tcon; - - tcon = readl(&pwm->tcon); - tcon &= ~TCON_START(pwm_id); - - writel(tcon, &pwm->tcon); -} - -static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq) -{ - unsigned long tin_parent_rate; - unsigned int div; - - tin_parent_rate = get_pwm_clk(); - - for (div = 2; div <= 16; div *= 2) { - if ((tin_parent_rate / (div << 16)) < freq) - return tin_parent_rate / div; - } - - return tin_parent_rate / 16; -} - -#define NS_IN_SEC 1000000000UL - -int pwm_config(int pwm_id, int duty_ns, int period_ns) -{ - const struct s5p_timer *pwm = - (struct s5p_timer *)samsung_get_base_timer(); - unsigned int offset; - unsigned long tin_rate; - unsigned long tin_ns; - unsigned long frequency; - unsigned long tcon; - unsigned long tcnt; - unsigned long tcmp; - - /* - * We currently avoid using 64bit arithmetic by using the - * fact that anything faster than 1GHz is easily representable - * by 32bits. - */ - if (period_ns > NS_IN_SEC || duty_ns > NS_IN_SEC || period_ns == 0) - return -ERANGE; - - if (duty_ns > period_ns) - return -EINVAL; - - frequency = NS_IN_SEC / period_ns; - - /* Check to see if we are changing the clock rate of the PWM */ - tin_rate = pwm_calc_tin(pwm_id, frequency); - - tin_ns = NS_IN_SEC / tin_rate; - tcnt = period_ns / tin_ns; - - /* Note, counters count down */ - tcmp = duty_ns / tin_ns; - tcmp = tcnt - tcmp; - - /* Update the PWM register block. */ - offset = pwm_id * 3; - if (pwm_id < 4) { - writel(tcnt, &pwm->tcntb0 + offset); - writel(tcmp, &pwm->tcmpb0 + offset); - } - - tcon = readl(&pwm->tcon); - tcon |= TCON_UPDATE(pwm_id); - if (pwm_id < 4) - tcon |= TCON_AUTO_RELOAD(pwm_id); - else - tcon |= TCON4_AUTO_RELOAD; - writel(tcon, &pwm->tcon); - - tcon &= ~TCON_UPDATE(pwm_id); - writel(tcon, &pwm->tcon); - - return 0; -} - -int pwm_init(int pwm_id, int div, int invert) -{ - u32 val; - const struct s5p_timer *pwm = - (struct s5p_timer *)samsung_get_base_timer(); - unsigned long ticks_per_period; - unsigned int offset, prescaler; - - /* - * Timer Freq(HZ) = - * PWM_CLK / { (prescaler_value + 1) * (divider_value) } - */ - - val = readl(&pwm->tcfg0); - if (pwm_id < 2) { - prescaler = PRESCALER_0; - val &= ~0xff; - val |= (prescaler & 0xff); - } else { - prescaler = PRESCALER_1; - val &= ~(0xff << 8); - val |= (prescaler & 0xff) << 8; - } - writel(val, &pwm->tcfg0); - val = readl(&pwm->tcfg1); - val &= ~(0xf << MUX_DIV_SHIFT(pwm_id)); - val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id); - writel(val, &pwm->tcfg1); - - if (pwm_id == 4) { - /* - * TODO(sjg): Use this as a countdown timer for now. We count - * down from the maximum value to 0, then reset. - */ - ticks_per_period = -1UL; - } else { - const unsigned long pwm_hz = 1000; - unsigned long timer_rate_hz = get_pwm_clk() / - ((prescaler + 1) * (1 << div)); - - ticks_per_period = timer_rate_hz / pwm_hz; - } - - /* set count value */ - offset = pwm_id * 3; - - writel(ticks_per_period, &pwm->tcntb0 + offset); - - val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id)); - if (invert && (pwm_id < 4)) - val |= TCON_INVERTER(pwm_id); - writel(val, &pwm->tcon); - - pwm_enable(pwm_id); - - return 0; -} diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c deleted file mode 100644 index 637593c..0000000 --- a/arch/arm/cpu/armv7/s5p-common/timer.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Heungjun Kim - * Inki Dae - * Minkyu Kang - * - * 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 -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -unsigned long get_current_tick(void); - -/* macro to read the 16 bit timer */ -static inline struct s5p_timer *s5p_get_base_timer(void) -{ - return (struct s5p_timer *)samsung_get_base_timer(); -} - -/** - * Read the countdown timer. - * - * This operates at 1MHz and counts downwards. It will wrap about every - * hour (2^32 microseconds). - * - * @return current value of timer - */ -static unsigned long timer_get_us_down(void) -{ - struct s5p_timer *const timer = s5p_get_base_timer(); - - return readl(&timer->tcnto4); -} - -int timer_init(void) -{ - /* PWM Timer 4 */ - pwm_init(4, MUX_DIV_4, 0); - pwm_config(4, 100000, 100000); - pwm_enable(4); - - /* Use this as the current monotonic time in us */ - gd->arch.timer_reset_value = 0; - - /* Use this as the last timer value we saw */ - gd->arch.lastinc = timer_get_us_down(); - reset_timer_masked(); - - return 0; -} - -/* - * timer without interrupts - */ -unsigned long get_timer(unsigned long base) -{ - unsigned long long time_ms; - - ulong now = timer_get_us_down(); - - /* - * Increment the time by the amount elapsed since the last read. - * The timer may have wrapped around, but it makes no difference to - * our arithmetic here. - */ - gd->arch.timer_reset_value += gd->arch.lastinc - now; - gd->arch.lastinc = now; - - /* Divide by 1000 to convert from us to ms */ - time_ms = gd->arch.timer_reset_value; - do_div(time_ms, 1000); - return time_ms - base; -} - -unsigned long __attribute__((no_instrument_function)) timer_get_us(void) -{ - static unsigned long base_time_us; - - struct s5p_timer *const timer = - (struct s5p_timer *)samsung_get_base_timer(); - unsigned long now_downward_us = readl(&timer->tcnto4); - - if (!base_time_us) - base_time_us = now_downward_us; - - /* Note that this timer counts downward. */ - return base_time_us - now_downward_us; -} - -/* delay x useconds */ -void __udelay(unsigned long usec) -{ - unsigned long count_value; - - count_value = timer_get_us_down(); - while ((int)(count_value - timer_get_us_down()) < (int)usec) - ; -} - -void reset_timer_masked(void) -{ - struct s5p_timer *const timer = s5p_get_base_timer(); - - /* reset time */ - gd->arch.lastinc = readl(&timer->tcnto4); - gd->arch.tbl = 0; -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -unsigned long get_tbclk(void) -{ - return CONFIG_SYS_HZ; -} diff --git a/arch/arm/cpu/samsung-common/Makefile b/arch/arm/cpu/samsung-common/Makefile new file mode 100644 index 0000000..cae22e8 --- /dev/null +++ b/arch/arm/cpu/samsung-common/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2009 Samsung Electronics +# Minkyu Kang +# +# 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)libsamsung-common.o + +ifndef CONFIG_SPL_BUILD +COBJS-$(CONFIG_PWM) += pwm.o +COBJS-y += timer.o +endif + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS)) + +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/cpu/samsung-common/pwm.c b/arch/arm/cpu/samsung-common/pwm.c new file mode 100644 index 0000000..6a6057f --- /dev/null +++ b/arch/arm/cpu/samsung-common/pwm.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * + * Donghwa Lee + * + * 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 +#include +#include +#include +#include +#include +#include + +int pwm_enable(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long tcon; + + tcon = readl(&pwm->tcon); + tcon |= TCON_START(pwm_id); + + writel(tcon, &pwm->tcon); + + return 0; +} + +void pwm_disable(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long tcon; + + tcon = readl(&pwm->tcon); + tcon &= ~TCON_START(pwm_id); + + writel(tcon, &pwm->tcon); +} + +static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq) +{ + unsigned long tin_parent_rate; + unsigned int div; + + tin_parent_rate = get_pwm_clk(); + + for (div = 2; div <= 16; div *= 2) { + if ((tin_parent_rate / (div << 16)) < freq) + return tin_parent_rate / div; + } + + return tin_parent_rate / 16; +} + +#define NS_IN_SEC 1000000000UL + +int pwm_config(int pwm_id, int duty_ns, int period_ns) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned int offset; + unsigned long tin_rate; + unsigned long tin_ns; + unsigned long frequency; + unsigned long tcon; + unsigned long tcnt; + unsigned long tcmp; + + /* + * We currently avoid using 64bit arithmetic by using the + * fact that anything faster than 1GHz is easily representable + * by 32bits. + */ + if (period_ns > NS_IN_SEC || duty_ns > NS_IN_SEC || period_ns == 0) + return -ERANGE; + + if (duty_ns > period_ns) + return -EINVAL; + + frequency = NS_IN_SEC / period_ns; + + /* Check to see if we are changing the clock rate of the PWM */ + tin_rate = pwm_calc_tin(pwm_id, frequency); + + tin_ns = NS_IN_SEC / tin_rate; + tcnt = period_ns / tin_ns; + + /* Note, counters count down */ + tcmp = duty_ns / tin_ns; + tcmp = tcnt - tcmp; + + /* Update the PWM register block. */ + offset = pwm_id * 3; + if (pwm_id < 4) { + writel(tcnt, &pwm->tcntb0 + offset); + writel(tcmp, &pwm->tcmpb0 + offset); + } + + tcon = readl(&pwm->tcon); + tcon |= TCON_UPDATE(pwm_id); + if (pwm_id < 4) + tcon |= TCON_AUTO_RELOAD(pwm_id); + else + tcon |= TCON4_AUTO_RELOAD; + writel(tcon, &pwm->tcon); + + tcon &= ~TCON_UPDATE(pwm_id); + writel(tcon, &pwm->tcon); + + return 0; +} + +int pwm_init(int pwm_id, int div, int invert) +{ + u32 val; + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long ticks_per_period; + unsigned int offset, prescaler; + + /* + * Timer Freq(HZ) = + * PWM_CLK / { (prescaler_value + 1) * (divider_value) } + */ + + val = readl(&pwm->tcfg0); + if (pwm_id < 2) { + prescaler = PRESCALER_0; + val &= ~0xff; + val |= (prescaler & 0xff); + } else { + prescaler = PRESCALER_1; + val &= ~(0xff << 8); + val |= (prescaler & 0xff) << 8; + } + writel(val, &pwm->tcfg0); + val = readl(&pwm->tcfg1); + val &= ~(0xf << MUX_DIV_SHIFT(pwm_id)); + val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id); + writel(val, &pwm->tcfg1); + + if (pwm_id == 4) { + /* + * TODO(sjg): Use this as a countdown timer for now. We count + * down from the maximum value to 0, then reset. + */ + ticks_per_period = -1UL; + } else { + const unsigned long pwm_hz = 1000; + unsigned long timer_rate_hz = get_pwm_clk() / + ((prescaler + 1) * (1 << div)); + + ticks_per_period = timer_rate_hz / pwm_hz; + } + + /* set count value */ + offset = pwm_id * 3; + + writel(ticks_per_period, &pwm->tcntb0 + offset); + + val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id)); + if (invert && (pwm_id < 4)) + val |= TCON_INVERTER(pwm_id); + writel(val, &pwm->tcon); + + pwm_enable(pwm_id); + + return 0; +} diff --git a/arch/arm/cpu/samsung-common/timer.c b/arch/arm/cpu/samsung-common/timer.c new file mode 100644 index 0000000..2b105e9 --- /dev/null +++ b/arch/arm/cpu/samsung-common/timer.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Heungjun Kim + * Inki Dae + * Minkyu Kang + * + * 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 +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long get_current_tick(void); + +/* macro to read the 16 bit timer */ +static inline struct s5p_timer *s5p_get_base_timer(void) +{ + return (struct s5p_timer *)samsung_get_base_timer(); +} + +/** + * Read the countdown timer. + * + * This operates at 1MHz and counts downwards. It will wrap about every + * hour (2^32 microseconds). + * + * @return current value of timer + */ +static unsigned long timer_get_us_down(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + + return readl(&timer->tcnto4); +} + +int timer_init(void) +{ + /* PWM Timer 4 */ + pwm_init(4, MUX_DIV_4, 0); + pwm_config(4, 100000, 100000); + pwm_enable(4); + + /* Use this as the current monotonic time in us */ + gd->arch.timer_reset_value = 0; + + /* Use this as the last timer value we saw */ + gd->arch.lastinc = timer_get_us_down(); + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long get_timer(unsigned long base) +{ + unsigned long long time_ms; + + ulong now = timer_get_us_down(); + + /* + * Increment the time by the amount elapsed since the last read. + * The timer may have wrapped around, but it makes no difference to + * our arithmetic here. + */ + gd->arch.timer_reset_value += gd->arch.lastinc - now; + gd->arch.lastinc = now; + + /* Divide by 1000 to convert from us to ms */ + time_ms = gd->arch.timer_reset_value; + do_div(time_ms, 1000); + return time_ms - base; +} + +unsigned long __attribute__((no_instrument_function)) timer_get_us(void) +{ + static unsigned long base_time_us; + + struct s5p_timer *const timer = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long now_downward_us = readl(&timer->tcnto4); + + if (!base_time_us) + base_time_us = now_downward_us; + + /* Note that this timer counts downward. */ + return base_time_us - now_downward_us; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ + unsigned long count_value; + + count_value = timer_get_us_down(); + while ((int)(count_value - timer_get_us_down()) < (int)usec) + ; +} + +void reset_timer_masked(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + + /* reset time */ + gd->arch.lastinc = readl(&timer->tcnto4); + gd->arch.tbl = 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/arch/arm/include/asm/arch-exynos/pwm.h b/arch/arm/include/asm/arch-exynos/pwm.h deleted file mode 100644 index 3e95160..0000000 --- a/arch/arm/include/asm/arch-exynos/pwm.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Kyungmin Park - * Minkyu Kang - * - * 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 - */ - -#ifndef __ASM_ARM_ARCH_PWM_H_ -#define __ASM_ARM_ARCH_PWM_H_ - -#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */ -#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ - -/* Divider MUX */ -#define MUX_DIV_1 0 /* 1/1 period */ -#define MUX_DIV_2 1 /* 1/2 period */ -#define MUX_DIV_4 2 /* 1/4 period */ -#define MUX_DIV_8 3 /* 1/8 period */ -#define MUX_DIV_16 4 /* 1/16 period */ - -#define MUX_DIV_SHIFT(x) (x * 4) - -#define TCON_OFFSET(x) ((x + 1) * (!!x) << 2) - -#define TCON_START(x) (1 << TCON_OFFSET(x)) -#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1)) -#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2)) -#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) -#define TCON4_AUTO_RELOAD (1 << 22) - -#ifndef __ASSEMBLY__ -struct s5p_timer { - unsigned int tcfg0; - unsigned int tcfg1; - unsigned int tcon; - unsigned int tcntb0; - unsigned int tcmpb0; - unsigned int tcnto0; - unsigned int tcntb1; - unsigned int tcmpb1; - unsigned int tcnto1; - unsigned int tcntb2; - unsigned int tcmpb2; - unsigned int tcnto2; - unsigned int tcntb3; - unsigned int tcmpb3; - unsigned int tcnto3; - unsigned int tcntb4; - unsigned int tcnto4; - unsigned int tintcstat; -}; -#endif /* __ASSEMBLY__ */ - -#endif diff --git a/arch/arm/include/asm/arch-s5pc1xx/pwm.h b/arch/arm/include/asm/arch-s5pc1xx/pwm.h deleted file mode 100644 index d0cf3cb..0000000 --- a/arch/arm/include/asm/arch-s5pc1xx/pwm.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Kyungmin Park - * Minkyu Kang - * - * 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 - */ - -#ifndef __ASM_ARM_ARCH_PWM_H_ -#define __ASM_ARM_ARCH_PWM_H_ - -#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */ -#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ - -/* Divider MUX */ -#define MUX_DIV_1 0 /* 1/1 period */ -#define MUX_DIV_2 1 /* 1/2 period */ -#define MUX_DIV_4 2 /* 1/4 period */ -#define MUX_DIV_8 3 /* 1/8 period */ -#define MUX_DIV_16 4 /* 1/16 period */ - -#define MUX_DIV_SHIFT(x) (x * 4) - -#define TCON_OFFSET(x) ((x + 1) * (!!x) << 2) - -#define TCON_START(x) (1 << TCON_OFFSET(x)) -#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1)) -#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2)) -#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) -#define TCON4_AUTO_RELOAD (1 << 22) - -#ifndef __ASSEMBLY__ -struct s5p_timer { - unsigned int tcfg0; - unsigned int tcfg1; - unsigned int tcon; - unsigned int tcntb0; - unsigned int tcmpb0; - unsigned int tcnto0; - unsigned int tcntb1; - unsigned int tcmpb1; - unsigned int tcnto1; - unsigned int tcntb2; - unsigned int tcmpb2; - unsigned int tcnto2; - unsigned int tcntb3; - unsigned int res1; - unsigned int tcnto3; - unsigned int tcntb4; - unsigned int tcnto4; - unsigned int tintcstat; -}; -#endif /* __ASSEMBLY__ */ - -#endif diff --git a/arch/arm/include/asm/samsung-common/pwm.h b/arch/arm/include/asm/samsung-common/pwm.h new file mode 100644 index 0000000..3e95160 --- /dev/null +++ b/arch/arm/include/asm/samsung-common/pwm.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Kyungmin Park + * Minkyu Kang + * + * 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 + */ + +#ifndef __ASM_ARM_ARCH_PWM_H_ +#define __ASM_ARM_ARCH_PWM_H_ + +#define PRESCALER_0 (8 - 1) /* prescaler of timer 0, 1 */ +#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ + +/* Divider MUX */ +#define MUX_DIV_1 0 /* 1/1 period */ +#define MUX_DIV_2 1 /* 1/2 period */ +#define MUX_DIV_4 2 /* 1/4 period */ +#define MUX_DIV_8 3 /* 1/8 period */ +#define MUX_DIV_16 4 /* 1/16 period */ + +#define MUX_DIV_SHIFT(x) (x * 4) + +#define TCON_OFFSET(x) ((x + 1) * (!!x) << 2) + +#define TCON_START(x) (1 << TCON_OFFSET(x)) +#define TCON_UPDATE(x) (1 << (TCON_OFFSET(x) + 1)) +#define TCON_INVERTER(x) (1 << (TCON_OFFSET(x) + 2)) +#define TCON_AUTO_RELOAD(x) (1 << (TCON_OFFSET(x) + 3)) +#define TCON4_AUTO_RELOAD (1 << 22) + +#ifndef __ASSEMBLY__ +struct s5p_timer { + unsigned int tcfg0; + unsigned int tcfg1; + unsigned int tcon; + unsigned int tcntb0; + unsigned int tcmpb0; + unsigned int tcnto0; + unsigned int tcntb1; + unsigned int tcmpb1; + unsigned int tcnto1; + unsigned int tcntb2; + unsigned int tcmpb2; + unsigned int tcnto2; + unsigned int tcntb3; + unsigned int tcmpb3; + unsigned int tcnto3; + unsigned int tcntb4; + unsigned int tcnto4; + unsigned int tintcstat; +}; +#endif /* __ASSEMBLY__ */ + +#endif