diff options
author | Gabe Black <gabeblack@google.com> | 2013-07-31 22:48:20 -0700 |
---|---|---|
committer | Patrick Georgi <patrick@georgi-clan.de> | 2013-12-21 10:48:53 +0100 |
commit | 713853a9c8fca493567548fe3cf0b8107b7fc138 (patch) | |
tree | d6fec9184dd2e2f86924bf77721224020247b216 /src/cpu/samsung/exynos5420 | |
parent | 9b764a0dcc67a7bbf6e74b35cdd9e3e7c6d59c83 (diff) | |
download | coreboot-713853a9c8fca493567548fe3cf0b8107b7fc138.tar.xz |
exynos5420: Get rid of the PWM code like on the 5250
The timer code was supposed to be using the mct, and also using the monotonic
timer infrastructure instead of the get_timer function. This change had been
made for the 5250 but not yet for the 5420.
Change-Id: I03a4fbb434f2346761f28fb6bd2218b526f2a4a2
Signed-off-by: Gabe Black <gabeblack@google.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/64159
Reviewed-by: Ronald G. Minnich <rminnich@chromium.org>
Commit-Queue: Gabe Black <gabeblack@chromium.org>
Tested-by: Gabe Black <gabeblack@chromium.org>
Reviewed-on: http://review.coreboot.org/4418
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'src/cpu/samsung/exynos5420')
-rw-r--r-- | src/cpu/samsung/exynos5420/Makefile.inc | 3 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/clock.c | 13 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/cpu.h | 3 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/dp-reg.c | 22 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/fb.c | 11 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/monotonic_timer.c | 2 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/pwm.c | 186 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/pwm.h | 70 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/timer.c | 62 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/timer.h | 25 |
10 files changed, 33 insertions, 364 deletions
diff --git a/src/cpu/samsung/exynos5420/Makefile.inc b/src/cpu/samsung/exynos5420/Makefile.inc index 854040948e..b92a23f558 100644 --- a/src/cpu/samsung/exynos5420/Makefile.inc +++ b/src/cpu/samsung/exynos5420/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/exynos5420/clock.c b/src/cpu/samsung/exynos5420/clock.c index 694f024ca8..b75540e099 100644 --- a/src/cpu/samsung/exynos5420/clock.c +++ b/src/cpu/samsung/exynos5420/clock.c @@ -19,9 +19,9 @@ #include <console/console.h> #include <stdlib.h> +#include <timer.h> #include <assert.h> #include <arch/io.h> -#include "timer.h" #include "clk.h" #include "cpu.h" #include "periph.h" @@ -522,7 +522,7 @@ 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 mono_time current, end; struct exynos5420_clock *clk = samsung_get_base_clock(); epll_con = readl(&clk->epll_con0); @@ -557,14 +557,17 @@ 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) & + while (!(readl(&clk->epll_con0) & (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) { - if (get_timer(start) > TIMEOUT_EPLL_LOCK) { + 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/exynos5420/cpu.h b/src/cpu/samsung/exynos5420/cpu.h index 251abeae1f..0d588da5f3 100644 --- a/src/cpu/samsung/exynos5420/cpu.h +++ b/src/cpu/samsung/exynos5420/cpu.h @@ -70,7 +70,6 @@ #define EXYNOS5_SPI1_BASE 0x12D30000 #define EXYNOS5_SPI2_BASE 0x12D40000 #define EXYNOS5_I2C_BASE 0x12C60000 -#define EXYNOS5_PWMTIMER_BASE 0x12DD0000 #define EXYNOS5_SPI_ISP_BASE 0x131A0000 #define EXYNOS5_I2S_BASE 0x12D60000 #define EXYNOS5_GPIO_PART3_BASE 0x13410000 /* C00..Y67 */ @@ -120,7 +119,6 @@ #define EXYNOS5420_I2C_8910_BASE 0x12E00000 #define EXYNOS5420_SPI_BASE 0x12D20000 #define EXYNOS5420_I2S_BASE 0x12D60000 -#define EXYNOS5420_PWMTIMER_BASE 0x12DD0000 #define EXYNOS5420_SPI_ISP_BASE 0x131A0000 #define EXYNOS5420_GPIO_PART2_BASE 0x13400000 #define EXYNOS5420_GPIO_PART3_BASE 0x13400C00 @@ -185,7 +183,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/exynos5420/dp-reg.c b/src/cpu/samsung/exynos5420/dp-reg.c index eb53356449..1d6a6b1d55 100644 --- a/src/cpu/samsung/exynos5420/dp-reg.c +++ b/src/cpu/samsung/exynos5420/dp-reg.c @@ -22,7 +22,7 @@ #include <console/console.h> #include <arch/io.h> #include <delay.h> -#include "timer.h" +#include <timer.h> #include "clk.h" #include "cpu.h" #include "periph.h" @@ -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/exynos5420/fb.c b/src/cpu/samsung/exynos5420/fb.c index 760f5ee4bf..3724a247c6 100644 --- a/src/cpu/samsung/exynos5420/fb.c +++ b/src/cpu/samsung/exynos5420/fb.c @@ -26,7 +26,6 @@ #include <timer.h> #include <delay.h> #include <console/console.h> -#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/exynos5420/monotonic_timer.c b/src/cpu/samsung/exynos5420/monotonic_timer.c index 6350af536f..57e3ae3104 100644 --- a/src/cpu/samsung/exynos5420/monotonic_timer.c +++ b/src/cpu/samsung/exynos5420/monotonic_timer.c @@ -37,7 +37,7 @@ void timer_monotonic_get(struct mono_time *mt) uint64_t usecs_elapsed; if (!mono_counter.initialized) { - init_timer(); + mct_start(); mono_counter.last_value = mct_raw_value(); mono_counter.initialized = 1; } diff --git a/src/cpu/samsung/exynos5420/pwm.c b/src/cpu/samsung/exynos5420/pwm.c deleted file mode 100644 index 7375f1b295..0000000000 --- a/src/cpu/samsung/exynos5420/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 <arch/io.h> -#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 *const 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/exynos5420/pwm.h b/src/cpu/samsung/exynos5420/pwm.h deleted file mode 100644 index 430006143d..0000000000 --- a/src/cpu/samsung/exynos5420/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_EXYNOS5420_PWM_H -#define CPU_SAMSUNG_EXYNOS5420_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/exynos5420/timer.c b/src/cpu/samsung/exynos5420/timer.c index 405effac5b..0c2e64143c 100644 --- a/src/cpu/samsung/exynos5420/timer.c +++ b/src/cpu/samsung/exynos5420/timer.c @@ -18,72 +18,14 @@ */ #include <console/console.h> -#include <arch/io.h> #include <timer.h> #include <delay.h> -#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/exynos5420/timer.h b/src/cpu/samsung/exynos5420/timer.h deleted file mode 100644 index f02d58ac63..0000000000 --- a/src/cpu/samsung/exynos5420/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_EXYNOS5420_TIMER_H -#define CPU_SAMSUNG_EXYNOS5420_TIMER_H - -unsigned long get_timer(unsigned long base); - -#endif |