From 9b764a0dcc67a7bbf6e74b35cdd9e3e7c6d59c83 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 30 Jul 2013 15:11:35 -0700 Subject: exynos5250: Get rid of the PWM timer code we shouldn't be using anymore This code was left over from U-Boot and was superceded by the MCT. Change-Id: Ia85e3b7281dcdd4740238dddd0dfc6f0ba2c94da Signed-off-by: Gabe Black Reviewed-on: https://gerrit.chromium.org/gerrit/63778 Commit-Queue: Gabe Black Reviewed-by: Gabe Black Tested-by: Gabe Black Reviewed-on: http://review.coreboot.org/4401 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/cpu/samsung/exynos5250/Makefile.inc | 3 - src/cpu/samsung/exynos5250/clock.c | 16 ++- src/cpu/samsung/exynos5250/cpu.h | 2 - src/cpu/samsung/exynos5250/dp-reg.c | 20 ++- src/cpu/samsung/exynos5250/fb.c | 11 +- src/cpu/samsung/exynos5250/monotonic_timer.c | 1 - src/cpu/samsung/exynos5250/pwm.c | 186 --------------------------- src/cpu/samsung/exynos5250/pwm.h | 70 ---------- src/cpu/samsung/exynos5250/timer.c | 62 +-------- src/cpu/samsung/exynos5250/timer.h | 25 ---- 10 files changed, 33 insertions(+), 363 deletions(-) delete mode 100644 src/cpu/samsung/exynos5250/pwm.c delete mode 100644 src/cpu/samsung/exynos5250/pwm.h delete mode 100644 src/cpu/samsung/exynos5250/timer.h diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc index 73fd3c5a4c..9b346c6ca3 100644 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ b/src/cpu/samsung/exynos5250/Makefile.inc @@ -14,7 +14,6 @@ bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c endif bootblock-y += wakeup.c bootblock-y += gpio.c -bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += pwm.c bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += timer.c romstage-y += spi.c @@ -30,7 +29,6 @@ ifeq ($(CONFIG_CONSOLE_SERIAL_UART),y) romstage-$(CONFIG_EARLY_CONSOLE) += uart.c endif romstage-y += wakeup.c -romstage-y += pwm.c # needed by timer.c romstage-y += gpio.c romstage-y += timer.c romstage-y += i2c.c @@ -46,7 +44,6 @@ ramstage-y += cpu.c ramstage-y += tmu.c ramstage-y += mct.c ramstage-y += monotonic_timer.c -ramstage-y += pwm.c # needed by timer.c ramstage-y += timer.c ramstage-y += gpio.c ramstage-y += i2c.c diff --git a/src/cpu/samsung/exynos5250/clock.c b/src/cpu/samsung/exynos5250/clock.c index 390fae30f6..a89ceb393a 100644 --- a/src/cpu/samsung/exynos5250/clock.c +++ b/src/cpu/samsung/exynos5250/clock.c @@ -610,9 +610,8 @@ int clock_epll_set_rate(unsigned long rate) unsigned int epll_con, epll_con_k; unsigned int i; unsigned int lockcnt; - unsigned int start; - struct exynos5_clock *clk = - samsung_get_base_clock(); + struct mono_time current, end; + struct exynos5_clock *clk = samsung_get_base_clock(); epll_con = readl(&clk->epll_con0); epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK << @@ -646,14 +645,19 @@ int clock_epll_set_rate(unsigned long rate) writel(epll_con, &clk->epll_con0); writel(epll_con_k, &clk->epll_con1); - start = get_timer(0); + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, TIMEOUT_EPLL_LOCK); while (!(readl(&clk->epll_con0) & (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) { - if (get_timer(start) > TIMEOUT_EPLL_LOCK) { - printk(BIOS_DEBUG, "%s: Timeout waiting for EPLL lock\n", __func__); + if (mono_time_after(¤t, &end)) { + printk(BIOS_DEBUG, + "%s: Timeout waiting for EPLL lock\n", + __func__); return -1; } + timer_monotonic_get(¤t); } return 0; diff --git a/src/cpu/samsung/exynos5250/cpu.h b/src/cpu/samsung/exynos5250/cpu.h index 63f17e28af..7b12c945d2 100644 --- a/src/cpu/samsung/exynos5250/cpu.h +++ b/src/cpu/samsung/exynos5250/cpu.h @@ -73,7 +73,6 @@ #define EXYNOS5_SPI1_BASE 0x12D30000 #define EXYNOS5_I2C_BASE 0x12C60000 #define EXYNOS5_SPI_BASE 0x12D20000 -#define EXYNOS5_PWMTIMER_BASE 0x12DD0000 #define EXYNOS5_SPI_ISP_BASE 0x131A0000 #define EXYNOS5_I2S_BASE 0x12D60000 #define EXYNOS5_GPIO_PART3_BASE 0x13400000 /* E00..H17 */ @@ -108,7 +107,6 @@ #define samsung_get_base_sromc() ((struct exynos5_sromc *)EXYNOS5_SROMC_BASE) #define samsung_get_base_swreset() ((struct exynos5_swreset *)EXYNOS5_SWRESET) #define samsung_get_base_sysreg() ((struct exynos5_sysreg *)EXYNOS5_SYSREG_BASE) -#define samsung_get_base_timer() ((struct s5p_timer *)EXYNOS5_PWMTIMER_BASE) #define samsung_get_base_uart() ((struct exynos5_uart *)EXYNOS5_UART_BASE) #define samsung_get_base_usb_phy() ((struct exynos5_usb_phy *)EXYNOS5_USBPHY_BASE) #define samsung_get_base_usb_otg() ((struct exynos5_usb_otg *)EXYNOS5_USBOTG_BASE) diff --git a/src/cpu/samsung/exynos5250/dp-reg.c b/src/cpu/samsung/exynos5250/dp-reg.c index ac4208d159..1cc70887ce 100644 --- a/src/cpu/samsung/exynos5250/dp-reg.c +++ b/src/cpu/samsung/exynos5250/dp-reg.c @@ -120,7 +120,7 @@ unsigned int s5p_dp_get_pll_lock_status(struct s5p_dp_device *dp) int s5p_dp_init_analog_func(struct s5p_dp_device *dp) { u32 reg; - u32 start; + struct mono_time current, end; struct exynos5_dp *base = dp->base; writel(0x00, &base->dp_phy_pd); @@ -135,13 +135,17 @@ int s5p_dp_init_analog_func(struct s5p_dp_device *dp) clrbits_le32(&base->dp_pll_ctl, DP_PLL_PD); - start = get_timer(0); + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, PLL_LOCK_TIMEOUT); + while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - if (get_timer(start) > PLL_LOCK_TIMEOUT) { + if (mono_time_after(¤t, &end)) { printk(BIOS_ERR, "%s: PLL is not locked\n", __func__); return -1; } + timer_monotonic_get(¤t); } } @@ -431,11 +435,14 @@ void s5p_dp_enable_video_master(struct s5p_dp_device *dp) int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp) { u32 reg, i = 0; - u32 start; + struct mono_time current, end; struct exynos5_dp *base = dp->base; /* Wait for 4 VSYNC_DET interrupts */ - start = get_timer(0); + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, STREAM_ON_TIMEOUT); + do { reg = readl(&base->common_int_sta_1); if (reg & VSYNC_DET) { @@ -444,7 +451,8 @@ int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp) } if (i == 4) break; - } while (get_timer(start) <= STREAM_ON_TIMEOUT); + timer_monotonic_get(¤t); + } while (mono_time_before(¤t, &end)); if (i != 4) { printk(BIOS_DEBUG, "s5p_dp_is_video_stream_on timeout\n"); diff --git a/src/cpu/samsung/exynos5250/fb.c b/src/cpu/samsung/exynos5250/fb.c index 760f5ee4bf..3724a247c6 100644 --- a/src/cpu/samsung/exynos5250/fb.c +++ b/src/cpu/samsung/exynos5250/fb.c @@ -26,7 +26,6 @@ #include #include #include -#include "timer.h" #include "cpu.h" #include "power.h" #include "sysreg.h" @@ -411,20 +410,24 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, { int pll_is_locked = 0; u32 data; - u32 start; int lane; + struct mono_time current, end; struct exynos5_dp *base = dp->base; /* Stop Video */ clrbits_le32(&base->video_ctl_1, VIDEO_EN); - start = get_timer(0); + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, PLL_LOCK_TIMEOUT); + while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) { - if (get_timer(start) > PLL_LOCK_TIMEOUT) { + if (mono_time_after(¤t, &end)) { /* Ignore this error, and try to continue */ printk(BIOS_ERR, "PLL is not locked yet.\n"); break; } + timer_monotonic_get(¤t); } printk(BIOS_SPEW, "PLL is %slocked\n", pll_is_locked == PLL_LOCKED ? "": "not "); diff --git a/src/cpu/samsung/exynos5250/monotonic_timer.c b/src/cpu/samsung/exynos5250/monotonic_timer.c index 6350af536f..d46d02a8d3 100644 --- a/src/cpu/samsung/exynos5250/monotonic_timer.c +++ b/src/cpu/samsung/exynos5250/monotonic_timer.c @@ -37,7 +37,6 @@ void timer_monotonic_get(struct mono_time *mt) uint64_t usecs_elapsed; if (!mono_counter.initialized) { - init_timer(); mono_counter.last_value = mct_raw_value(); mono_counter.initialized = 1; } diff --git a/src/cpu/samsung/exynos5250/pwm.c b/src/cpu/samsung/exynos5250/pwm.c deleted file mode 100644 index eeb67211c6..0000000000 --- a/src/cpu/samsung/exynos5250/pwm.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 Samsung Electronics - * - * 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; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include "clk.h" -#include "cpu.h" -#include "periph.h" -#include "pwm.h" - -int pwm_enable(int pwm_id) -{ - struct s5p_timer *const pwm = samsung_get_base_timer(); - unsigned long tcon; - - tcon = readl(&pwm->tcon); - tcon |= TCON_START(pwm_id); - - writel(tcon, &pwm->tcon); - - return 0; -} - -int pwm_check_enabled(int pwm_id) -{ - const struct s5p_timer *pwm = samsung_get_base_timer(); - const unsigned long tcon = readl(&pwm->tcon); - - return tcon & TCON_START(pwm_id); -} - -void pwm_disable(int pwm_id) -{ - struct s5p_timer *const pwm = 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 = clock_get_periph_rate(PERIPH_ID_PWM0); - - 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) -{ - struct s5p_timer *const pwm = 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 -1; - - if (duty_ns > period_ns) - return -1; - - 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; - struct s5p_timer *const pwm = 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 = clock_get_periph_rate( - PERIPH_ID_PWM0) / ((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/src/cpu/samsung/exynos5250/pwm.h b/src/cpu/samsung/exynos5250/pwm.h deleted file mode 100644 index 948bb6d0a8..0000000000 --- a/src/cpu/samsung/exynos5250/pwm.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2009 Samsung Electronics - * - * 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; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef CPU_SAMSUNG_EXYNOS5250_PWM_H -#define CPU_SAMSUNG_EXYNOS5250_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) - -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; -}; - -int pwm_config(int pwm_id, int duty_ns, int period_ns); -int pwm_check_enabled(int pwm_id); -void pwm_disable(int pwm_id); -int pwm_enable(int pwm_id); -int pwm_init(int pwm_id, int div, int invert); - -#endif diff --git a/src/cpu/samsung/exynos5250/timer.c b/src/cpu/samsung/exynos5250/timer.c index 405effac5b..0c2e64143c 100644 --- a/src/cpu/samsung/exynos5250/timer.c +++ b/src/cpu/samsung/exynos5250/timer.c @@ -18,72 +18,14 @@ */ #include -#include #include #include -#include "timer.h" -#include "pwm.h" -#include "clk.h" -#include "cpu.h" - -static unsigned long long timer_reset_value; -static unsigned long lastinc; - -/* macro to read the 16 bit timer */ -static inline struct s5p_timer *s5p_get_base_timer(void) -{ - return 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); -} +#include "clk.h" void init_timer(void) { - /* Timer may have been enabled in SPL */ - if (!pwm_check_enabled(4)) { - /* 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 */ - timer_reset_value = 0; - - /* Use this as the last timer value we saw */ - lastinc = timer_get_us_down(); - } -} - -/* - * timer without interrupts - */ -unsigned long get_timer(unsigned long base) -{ - unsigned long 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. - */ - timer_reset_value += lastinc - now; - lastinc = now; - - /* Divide by 1000 to convert from us to ms */ - return timer_reset_value / 1000 - base; + mct_start(); } /* delay x useconds */ diff --git a/src/cpu/samsung/exynos5250/timer.h b/src/cpu/samsung/exynos5250/timer.h deleted file mode 100644 index 100c500980..0000000000 --- a/src/cpu/samsung/exynos5250/timer.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2013 Google Inc. - * - * 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; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef CPU_SAMSUNG_EXYNOS5250_TIMER_H -#define CPU_SAMSUNG_EXYNOS5250_TIMER_H - -unsigned long get_timer(unsigned long base); - -#endif -- cgit v1.2.3