Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2405
-gerrit
commit dda6d0735a68ca0b85ddac103e8f71edeec35b79 Author: Stefan Reinauer reinauer@chromium.org Date: Thu Feb 14 16:35:47 2013 -0800
Exynos5: Drop S5P directory and merge files
s5p-common mostly contained duplicate files, drop the whole directory and merge the few pieces that we are using into exynos5-common.
Change-Id: I5f18e8a6d2379d719ab6bbbf817fe15bda70d17f Signed-off-by: Stefan Reinauer reinauer@google.com --- src/cpu/samsung/Kconfig | 5 - src/cpu/samsung/Makefile.inc | 3 - src/cpu/samsung/exynos5-common/Makefile.inc | 18 + src/cpu/samsung/exynos5-common/clk.h | 5 +- src/cpu/samsung/exynos5-common/clock.h | 94 +++++ src/cpu/samsung/exynos5-common/cpu.h | 93 ++++- src/cpu/samsung/exynos5-common/cpu_info.c | 128 ++++++ src/cpu/samsung/exynos5-common/gpio.c | 501 +++++++++++++++++++++++ src/cpu/samsung/exynos5-common/gpio.h | 156 ++++++- src/cpu/samsung/exynos5-common/i2c.c | 612 ++++++++++++++++++++++++++++ src/cpu/samsung/exynos5-common/i2c.h | 43 ++ src/cpu/samsung/exynos5-common/power.h | 42 ++ src/cpu/samsung/exynos5-common/pwm.c | 199 +++++++++ src/cpu/samsung/exynos5-common/pwm.h | 6 + src/cpu/samsung/exynos5-common/sromc.c | 49 +++ src/cpu/samsung/exynos5-common/timer.c | 150 +++++++ src/cpu/samsung/exynos5-common/watchdog.h | 57 +++ src/cpu/samsung/exynos5-common/wdt.c | 59 +++ src/cpu/samsung/exynos5250/Makefile.inc | 2 +- src/cpu/samsung/exynos5250/clock.c | 2 +- src/cpu/samsung/exynos5250/clock_init.c | 2 +- src/cpu/samsung/exynos5250/dmc_init_ddr3.c | 2 +- src/cpu/samsung/exynos5250/power.c | 2 +- src/cpu/samsung/s5p-common/Makefile.inc | 17 - src/cpu/samsung/s5p-common/clk.h | 38 -- src/cpu/samsung/s5p-common/clock.h | 94 ----- src/cpu/samsung/s5p-common/cpu.h | 116 ------ src/cpu/samsung/s5p-common/cpu_info.c | 128 ------ src/cpu/samsung/s5p-common/gpio.h | 173 -------- src/cpu/samsung/s5p-common/power.h | 42 -- src/cpu/samsung/s5p-common/pwm.c | 205 ---------- src/cpu/samsung/s5p-common/pwm.h | 75 ---- src/cpu/samsung/s5p-common/s3c24x0_i2c.c | 612 ---------------------------- src/cpu/samsung/s5p-common/s3c24x0_i2c.h | 43 -- src/cpu/samsung/s5p-common/s5p_gpio.c | 516 ----------------------- src/cpu/samsung/s5p-common/sromc.c | 49 --- src/cpu/samsung/s5p-common/sromc.h | 53 --- src/cpu/samsung/s5p-common/timer.c | 152 ------- src/cpu/samsung/s5p-common/uart.h | 58 --- src/cpu/samsung/s5p-common/watchdog.h | 57 --- src/cpu/samsung/s5p-common/wdt.c | 59 --- 41 files changed, 2206 insertions(+), 2511 deletions(-)
diff --git a/src/cpu/samsung/Kconfig b/src/cpu/samsung/Kconfig index 9f833f3..92b6460 100644 --- a/src/cpu/samsung/Kconfig +++ b/src/cpu/samsung/Kconfig @@ -1,10 +1,5 @@ -config CPU_SAMSUNG_EXYNOS - bool - default n - config CPU_SAMSUNG_EXYNOS5 depends on ARCH_ARMV7 - select CPU_SAMSUNG_EXYNOS select HAVE_UART_SPECIAL select DEFAULT_EARLY_CONSOLE bool diff --git a/src/cpu/samsung/Makefile.inc b/src/cpu/samsung/Makefile.inc index b6fcd4e..97e9aab 100644 --- a/src/cpu/samsung/Makefile.inc +++ b/src/cpu/samsung/Makefile.inc @@ -1,5 +1,2 @@ subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS5) += exynos5-common subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS5) += exynos5250 - -# S5P is a predecessor to Exynos -subdirs-$(CONFIG_CPU_SAMSUNG_EXYNOS) += s5p-common diff --git a/src/cpu/samsung/exynos5-common/Makefile.inc b/src/cpu/samsung/exynos5-common/Makefile.inc index ff86fbd..47abe0f 100644 --- a/src/cpu/samsung/exynos5-common/Makefile.inc +++ b/src/cpu/samsung/exynos5-common/Makefile.inc @@ -1,3 +1,21 @@ romstage-y += spi.c ramstage-y += spi.c bootblock-y += spi.c + +bootblock-y += gpio.c +bootblock-$(CONFIG_EARLY_CONSOLE) += pwm.c +bootblock-$(CONFIG_EARLY_CONSOLE) += timer.c + +romstage-y += pwm.c # needed by timer.c +romstage-y += gpio.c +romstage-y += timer.c +romstage-y += i2c.c + +#romstage-y += wdt.c +#romstage-y += sromc.c + +ramstage-y += cpu_info.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/exynos5-common/clk.h b/src/cpu/samsung/exynos5-common/clk.h index eb3b253..9de4f45 100644 --- a/src/cpu/samsung/exynos5-common/clk.h +++ b/src/cpu/samsung/exynos5-common/clk.h @@ -52,12 +52,11 @@ struct clk_bit_info { s8 prediv_bit; };
-/* FIXME(dhendrix) conflicts with s5p-common/clk.h */ -#if 0 unsigned long get_pll_clk(int pllreg); unsigned long get_arm_clk(void); +unsigned long get_pwm_clk(void); +unsigned long get_uart_clk(int dev_index); void set_mmc_clk(int dev_index, unsigned int div); -#endif
/** * get the clk frequency of the required peripherial diff --git a/src/cpu/samsung/exynos5-common/clock.h b/src/cpu/samsung/exynos5-common/clock.h new file mode 100644 index 0000000..c0cd896 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/clock.h @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang mk7.kang@samsung.com + * Heungjun Kim riverful.kim@samsung.com + * + * 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_CLOCK_H_ +#define __ASM_ARM_ARCH_CLOCK_H_ + +#ifndef __ASSEMBLER__ +struct s5pc100_clock { + unsigned int apll_lock; + unsigned int mpll_lock; + unsigned int epll_lock; + unsigned int hpll_lock; + unsigned char res1[0xf0]; + unsigned int apll_con; + unsigned int mpll_con; + unsigned int epll_con; + unsigned int hpll_con; + unsigned char res2[0xf0]; + unsigned int src0; + unsigned int src1; + unsigned int src2; + unsigned int src3; + unsigned char res3[0xf0]; + unsigned int div0; + unsigned int div1; + unsigned int div2; + unsigned int div3; + unsigned int div4; + unsigned char res4[0x1ec]; + unsigned int gate_d00; + unsigned int gate_d01; + unsigned int gate_d02; + unsigned char res5[0x54]; + unsigned int gate_sclk0; + unsigned int gate_sclk1; +}; + +struct s5pc110_clock { + unsigned int apll_lock; + unsigned char res1[0x4]; + unsigned int mpll_lock; + unsigned char res2[0x4]; + unsigned int epll_lock; + unsigned char res3[0xc]; + unsigned int vpll_lock; + unsigned char res4[0xdc]; + unsigned int apll_con; + unsigned char res5[0x4]; + unsigned int mpll_con; + unsigned char res6[0x4]; + unsigned int epll_con; + unsigned char res7[0xc]; + unsigned int vpll_con; + unsigned char res8[0xdc]; + unsigned int src0; + unsigned int src1; + unsigned int src2; + unsigned int src3; + unsigned char res9[0xf0]; + unsigned int div0; + unsigned int div1; + unsigned int div2; + unsigned int div3; + unsigned int div4; + unsigned char res10[0x1ec]; + unsigned int gate_d00; + unsigned int gate_d01; + unsigned int gate_d02; + unsigned char res11[0x54]; + unsigned int gate_sclk0; + unsigned int gate_sclk1; +}; +#endif + +#endif diff --git a/src/cpu/samsung/exynos5-common/cpu.h b/src/cpu/samsung/exynos5-common/cpu.h index e68de86..5a18913 100644 --- a/src/cpu/samsung/exynos5-common/cpu.h +++ b/src/cpu/samsung/exynos5-common/cpu.h @@ -1,6 +1,7 @@ /* - * (C) Copyright 2010 Samsung Electronics + * (C) Copyright 2009-2010 Samsung Electronics * Minkyu Kang mk7.kang@samsung.com + * Heungjun Kim riverful.kim@samsung.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -22,7 +23,95 @@ #ifndef _EXYNOS_COMMON_CPU_H #define _EXYNOS_COMMON_CPU_H
-#include <cpu/samsung/s5p-common/cpu.h> +#define S5PC1XX_ADDR_BASE 0xE0000000 + +/* S5PC100 */ +#define S5PC100_PRO_ID 0xE0000000 +#define S5PC100_CLOCK_BASE 0xE0100000 +#define S5PC100_GPIO_BASE 0xE0300000 +#define S5PC100_VIC0_BASE 0xE4000000 +#define S5PC100_VIC1_BASE 0xE4100000 +#define S5PC100_VIC2_BASE 0xE4200000 +#define S5PC100_DMC_BASE 0xE6000000 +#define S5PC100_SROMC_BASE 0xE7000000 +#define S5PC100_ONENAND_BASE 0xE7100000 +#define S5PC100_PWMTIMER_BASE 0xEA000000 +#define S5PC100_WATCHDOG_BASE 0xEA200000 +#define S5PC100_UART_BASE 0xEC000000 +#define S5PC100_MMC_BASE 0xED800000 + +/* S5PC110 */ +#define S5PC110_PRO_ID 0xE0000000 +#define S5PC110_CLOCK_BASE 0xE0100000 +#define S5PC110_GPIO_BASE 0xE0200000 +#define S5PC110_PWMTIMER_BASE 0xE2500000 +#define S5PC110_WATCHDOG_BASE 0xE2700000 +#define S5PC110_UART_BASE 0xE2900000 +#define S5PC110_SROMC_BASE 0xE8000000 +#define S5PC110_MMC_BASE 0xEB000000 +#define S5PC110_DMC0_BASE 0xF0000000 +#define S5PC110_DMC1_BASE 0xF1400000 +#define S5PC110_VIC0_BASE 0xF2000000 +#define S5PC110_VIC1_BASE 0xF2100000 +#define S5PC110_VIC2_BASE 0xF2200000 +#define S5PC110_VIC3_BASE 0xF2300000 +#define S5PC110_OTG_BASE 0xEC000000 +#define S5PC110_PHY_BASE 0xEC100000 +#define S5PC110_USB_PHY_CONTROL 0xE010E80C + + +#include <arch/io.h> +/* CPU detection macros */ +extern unsigned int s5p_cpu_id; + +/* FIXME(dhendrix): conflicts with the one in cpu_info.c ... */ +#if 0 +inline void s5p_set_cpu_id(void) +{ + s5p_cpu_id = readl(S5PC100_PRO_ID); + s5p_cpu_id = 0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12); +} +#endif +inline void s5p_set_cpu_id(void); + +#define IS_SAMSUNG_TYPE(type, id) \ +static inline int cpu_is_##type(void) \ +{ \ + return s5p_cpu_id == id ? 1 : 0; \ +} + +IS_SAMSUNG_TYPE(s5pc100, 0xc100) +IS_SAMSUNG_TYPE(s5pc110, 0xc110) + +/* + * FIXME(dhendrix): collides with SAMSUNG_BASE in exynos header files. We + * don't really care about old S5P processors right now. + */ +#if 0 +#define SAMSUNG_BASE(device, base) \ +static inline unsigned int samsung_get_base_##device(void) \ +{ \ + if (cpu_is_s5pc100()) \ + return S5PC100_##base; \ + else if (cpu_is_s5pc110()) \ + return S5PC110_##base; \ + else \ + return 0; \ +} + +SAMSUNG_BASE(clock, CLOCK_BASE) +SAMSUNG_BASE(gpio, GPIO_BASE) +SAMSUNG_BASE(pro_id, PRO_ID) +SAMSUNG_BASE(mmc, MMC_BASE) +SAMSUNG_BASE(sromc, SROMC_BASE) +SAMSUNG_BASE(timer, PWMTIMER_BASE) +SAMSUNG_BASE(uart, UART_BASE) +SAMSUNG_BASE(watchdog, WATCHDOG_BASE) +#endif + +int s5p_get_cpu_rev(void); +//void s5p_set_cpu_id(void); +int s5p_get_cpu_id(void);
#define DEVICE_NOT_AVAILABLE 0
diff --git a/src/cpu/samsung/exynos5-common/cpu_info.c b/src/cpu/samsung/exynos5-common/cpu_info.c new file mode 100644 index 0000000..dec3c77 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/cpu_info.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang mk7.kang@samsung.com + * + * 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 <common.h> +#if 0 +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/clock.h> +#include <asm/arch/dmc.h> +#endif +#include <arch/io.h> + +#include <cpu/samsung/exynos5-common/clk.h> +#include <cpu/samsung/exynos5-common/clock.h> +#include <cpu/samsung/exynos5-common/cpu.h> + +#include <cpu/samsung/exynos5250/dmc.h> +#include <cpu/samsung/exynos5-common/cpu.h> /* for EXYNOS_PRO_ID */ + +/* FIXME(dhendrix): consolidate samsung ID code/#defines to a common location */ +#include <cpu/samsung/exynos5250/setup.h> /* cpu_info_init() prototype */ + +/* + * The following CPU infos are initialized in lowlevel_init(). They should be + * put in the .data section. Otherwise, a compile will put them in the .bss + * section since they don't have initial values. The relocation code which + * runs after lowlevel_init() will reset them to zero. + */ +unsigned int s5p_cpu_id __attribute__((section(".data"))); +unsigned int s5p_cpu_rev __attribute__((section(".data"))); + +void cpu_info_init(void) +{ + s5p_set_cpu_id(); +} + +int s5p_get_cpu_id(void) +{ + return s5p_cpu_id; +} + +int s5p_get_cpu_rev(void) +{ + return s5p_cpu_rev; +} + +void s5p_set_cpu_id(void) +{ + s5p_cpu_id = readl(EXYNOS_PRO_ID); + s5p_cpu_id = (0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12)); + + /* + * 0xC200: EXYNOS4210 EVT0 + * 0xC210: EXYNOS4210 EVT1 + */ + if (s5p_cpu_id == 0xC200) { + s5p_cpu_id |= 0x10; + s5p_cpu_rev = 0; + } else if (s5p_cpu_id == 0xC210) { + s5p_cpu_rev = 1; + } +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU: S5P%X @ %sMHz\n", + s5p_cpu_id, strmhz(buf, get_arm_clk())); + + return 0; +} +#endif + +#if 0 +void board_show_dram(ulong size) +{ + enum ddr_mode mem_type; + unsigned frequency_mhz; + unsigned arm_freq; + enum mem_manuf mem_manuf; + char buf[32]; + int ret; + + /* Get settings from the fdt */ + ret = clock_get_mem_selection(&mem_type, &frequency_mhz, + &arm_freq, &mem_manuf); + if (ret) + panic("Invalid DRAM information"); + + puts("DRAM: "); + print_size(size, " "); + printf("%s %s @ %sMHz", + clock_get_mem_manuf_name(mem_manuf), + clock_get_mem_type_name(mem_type), + strmhz(buf, frequency_mhz)); + putc('\n'); +} +#endif + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + cpu_info_init(); + + return 0; +} +#endif diff --git a/src/cpu/samsung/exynos5-common/gpio.c b/src/cpu/samsung/exynos5-common/gpio.c new file mode 100644 index 0000000..c9c4c26 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/gpio.c @@ -0,0 +1,501 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang mk7.kang@samsung.com + * + * 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 + */ + +/* FIXME(dhendrix): fix this up so it doesn't require a bunch of #ifdefs... */ +#include <common.h> +#include <gpio.h> +//#include <arch/io.h> +#include <gpio.h> +#include <arch/gpio.h> +#include <console/console.h> +#include <cpu/samsung/exynos5-common/gpio.h> +#include <cpu/samsung/exynos5250/gpio.h> /* FIXME: for gpio_decode_number prototype */ + +#define CON_MASK(x) (0xf << ((x) << 2)) +#define CON_SFR(x, v) ((v) << ((x) << 2)) + +#define DAT_MASK(x) (0x1 << (x)) +#define DAT_SET(x) (0x1 << (x)) + +#define PULL_MASK(x) (0x3 << ((x) << 1)) +#define PULL_MODE(x, v) ((v) << ((x) << 1)) + +#define DRV_MASK(x) (0x3 << ((x) << 1)) +#define DRV_SET(x, m) ((m) << ((x) << 1)) +#define RATE_MASK(x) (0x1 << (x + 16)) +#define RATE_SET(x) (0x1 << (x + 16)) + +struct gpio_info { + unsigned int reg_addr; /* Address of register for this part */ + unsigned int max_gpio; /* Maximum GPIO in this part */ +}; + +#include <cpu/samsung/exynos5250/cpu.h> +static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = { + { EXYNOS5_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 }, + { EXYNOS5_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 }, + { EXYNOS5_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 }, + { EXYNOS5_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 }, + { EXYNOS5_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 }, + { EXYNOS5_GPIO_PART6_BASE, GPIO_MAX_PORT }, +}; + +#define HAVE_GENERIC_GPIO + +/* This macro gets gpio pin offset from 0..7 */ +#define GPIO_BIT(x) ((x) & 0x7) + +//#ifdef HAVE_GENERIC_GPIO +static struct s5p_gpio_bank *gpio_get_bank(unsigned int gpio) +{ + const struct gpio_info *data; + unsigned int upto; + int i; + + for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS; + i++, upto = data->max_gpio, data++) { + if (gpio < data->max_gpio) { + struct s5p_gpio_bank *bank; + + bank = (struct s5p_gpio_bank *)data->reg_addr; + bank += (gpio - upto) / GPIO_PER_BANK; + return bank; + } + } + + assert(gpio < GPIO_MAX_PORT); /* ...which it will not be */ + return NULL; +} +//#endif + +/* TODO: Deprecation this interface in favour of asm-generic/gpio.h */ +void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) +{ + unsigned int value; + + value = readl(&bank->con); + value &= ~CON_MASK(gpio); + value |= CON_SFR(gpio, cfg); + writel(value, &bank->con); +} + +void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en) +{ + unsigned int value; + + s5p_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_OUTPUT); + + value = readl(&bank->dat); + value &= ~DAT_MASK(gpio); + if (en) + value |= DAT_SET(gpio); + writel(value, &bank->dat); +} + +void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio) +{ + s5p_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_INPUT); +} + +void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) +{ + unsigned int value; + + value = readl(&bank->dat); + value &= ~DAT_MASK(gpio); + if (en) + value |= DAT_SET(gpio); + writel(value, &bank->dat); +} + +unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) +{ + unsigned int value; + + value = readl(&bank->dat); + return !!(value & DAT_MASK(gpio)); +} + +void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) +{ + unsigned int value; + + value = readl(&bank->pull); + value &= ~PULL_MASK(gpio); + + switch (mode) { + case EXYNOS_GPIO_PULL_DOWN: + case EXYNOS_GPIO_PULL_UP: + value |= PULL_MODE(gpio, mode); + break; + default: + break; + } + + writel(value, &bank->pull); +} + +void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) +{ + unsigned int value; + + value = readl(&bank->drv); + value &= ~DRV_MASK(gpio); + + switch (mode) { + case EXYNOS_GPIO_DRV_1X: + case EXYNOS_GPIO_DRV_2X: + case EXYNOS_GPIO_DRV_3X: + case EXYNOS_GPIO_DRV_4X: + value |= DRV_SET(gpio, mode); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) +{ + unsigned int value; + + value = readl(&bank->drv); + value &= ~RATE_MASK(gpio); + + switch (mode) { + case EXYNOS_GPIO_DRV_FAST: + case EXYNOS_GPIO_DRV_SLOW: + value |= RATE_SET(gpio); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +/* Common GPIO API - only available on Exynos5 */ +/* FIXME(dhendrix): If this stuff is really only applicable to exynos5, + move it to a more sensible location. */ +#ifdef HAVE_GENERIC_GPIO + +void gpio_cfg_pin(int gpio, int cfg) +{ + unsigned int value; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->con); + value &= ~CON_MASK(GPIO_BIT(gpio)); + value |= CON_SFR(GPIO_BIT(gpio), cfg); + writel(value, &bank->con); +} + +static int gpio_get_cfg(int gpio) +{ + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + int shift = GPIO_BIT(gpio) << 2; + + return (readl(&bank->con) & CON_MASK(GPIO_BIT(gpio))) >> shift; +} + +void gpio_set_pull(int gpio, int mode) +{ + unsigned int value; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->pull); + value &= ~PULL_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case EXYNOS_GPIO_PULL_DOWN: + case EXYNOS_GPIO_PULL_UP: + value |= PULL_MODE(GPIO_BIT(gpio), mode); + break; + default: + break; + } + + writel(value, &bank->pull); +} + +void gpio_set_drv(int gpio, int mode) +{ + unsigned int value; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->drv); + value &= ~DRV_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case EXYNOS_GPIO_DRV_1X: + case EXYNOS_GPIO_DRV_2X: + case EXYNOS_GPIO_DRV_3X: + case EXYNOS_GPIO_DRV_4X: + value |= DRV_SET(GPIO_BIT(gpio), mode); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +void gpio_set_rate(int gpio, int mode) +{ + unsigned int value; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->drv); + value &= ~RATE_MASK(GPIO_BIT(gpio)); + + switch (mode) { + case EXYNOS_GPIO_DRV_FAST: + case EXYNOS_GPIO_DRV_SLOW: + value |= RATE_SET(GPIO_BIT(gpio)); + break; + default: + return; + } + + writel(value, &bank->drv); +} + +int gpio_request(unsigned gpio, const char *label) +{ + return 0; +} + +int gpio_free(unsigned gpio) +{ + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + gpio_cfg_pin(gpio, EXYNOS_GPIO_INPUT); + + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + unsigned int val; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + gpio_cfg_pin(gpio, EXYNOS_GPIO_OUTPUT); + + val = readl(&bank->dat); + val &= ~DAT_MASK(GPIO_BIT(gpio)); + if (value) + val |= DAT_SET(GPIO_BIT(gpio)); + writel(val, &bank->dat); + + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + unsigned int value; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + value = readl(&bank->dat); + return !!(value & DAT_MASK(GPIO_BIT(gpio))); +} + +int gpio_set_value(unsigned gpio, int value) +{ + unsigned int val; + struct s5p_gpio_bank *bank = gpio_get_bank(gpio); + + val = readl(&bank->dat); + val &= ~DAT_MASK(GPIO_BIT(gpio)); + if (value) + val |= DAT_SET(GPIO_BIT(gpio)); + writel(val, &bank->dat); + + return 0; +} +#else + +static int s5p_gpio_get_pin(unsigned gpio) +{ + return gpio % GPIO_PER_BANK; +} + +/* + * If we have the old-style GPIO numbering setup, use these functions + * which don't necessary provide sequentially increasing GPIO numbers. + */ +static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio) +{ + int bank = gpio / GPIO_PER_BANK; + bank *= sizeof(struct s5p_gpio_bank); + + return (struct s5p_gpio_bank *) (s5p_gpio_base(gpio) + bank); +} + +int gpio_request(unsigned gpio, const char *label) +{ + return 0; +} + +int gpio_free(unsigned gpio) +{ + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + s5p_gpio_direction_input(s5p_gpio_get_bank(gpio), + s5p_gpio_get_pin(gpio)); + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + s5p_gpio_direction_output(s5p_gpio_get_bank(gpio), + s5p_gpio_get_pin(gpio), value); + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio), + s5p_gpio_get_pin(gpio)); +} + +int gpio_set_value(unsigned gpio, int value) +{ + s5p_gpio_set_value(s5p_gpio_get_bank(gpio), + s5p_gpio_get_pin(gpio), value); + + return 0; +} + +#endif /* HAVE_GENERIC_GPIO */ + +/* + * Add a delay here to give the lines time to settle + * TODO(sjg): 1us does not always work, 2 is stable, so use 5 to be safe + * Come back to this and sort out what the datasheet says + */ +#define GPIO_DELAY_US 5 + +#ifndef __BOOT_BLOCK__ +/* + * FIXME(dhendrix): These functions use udelay, which has dependencies on + * pwm code and timer code. These aren't necessary for the bootblock and + * bloat the image significantly. + */ +int gpio_read_mvl3(unsigned gpio) +{ + int high, low; + enum mvl3 value; + + if (gpio >= GPIO_MAX_PORT) + return -1; + + gpio_direction_input(gpio); + gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP); + udelay(GPIO_DELAY_US); + high = gpio_get_value(gpio); + gpio_set_pull(gpio, EXYNOS_GPIO_PULL_DOWN); + udelay(GPIO_DELAY_US); + low = gpio_get_value(gpio); + + if (high && low) /* external pullup */ + value = LOGIC_1; + else if (!high && !low) /* external pulldown */ + value = LOGIC_0; + else /* floating */ + value = LOGIC_Z; + + /* + * Check if line is externally pulled high and + * configure the internal pullup to match. For + * floating and pulldowns, the GPIO is already + * configured with an internal pulldown from the + * above test. + */ + if (value == LOGIC_1) + gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP); + + return value; +} + +int gpio_decode_number(unsigned gpio_list[], int count) +{ + int result = 0; + int multiplier = 1; + int gpio, i, value; + enum mvl3 mvl3; + + for (i = 0; i < count; i++) { + gpio = gpio_list[i]; + + mvl3 = gpio_read_mvl3(gpio); + if (mvl3 == LOGIC_1) + value = 2; + else if (mvl3 == LOGIC_0) + value = 1; + else if (mvl3 == LOGIC_Z) + value = 0; + else + return -1; + + result += value * multiplier; + multiplier *= 3; + } + + return result; +} +#endif /* __BOOT_BLOCK__ */ + +static const char *get_cfg_name(int cfg) +{ + static char name[8]; + + if (cfg == EXYNOS_GPIO_INPUT) + return "input"; + else if (cfg == EXYNOS_GPIO_OUTPUT) + return "output"; + printk(BIOS_INFO, "func %d", cfg); +// sprintf(name, "func %d", cfg); + + return name; +} + +/* + * Display Exynos GPIO information + */ +void gpio_info(void) +{ + unsigned gpio; + + for (gpio = 0; gpio < GPIO_MAX_PORT; gpio++) { + int cfg = gpio_get_cfg(gpio); + + printk(BIOS_INFO, "GPIO_%-3d: %s", gpio, get_cfg_name(cfg)); + if (cfg == EXYNOS_GPIO_INPUT || cfg == EXYNOS_GPIO_OUTPUT) + printk(BIOS_INFO, ", value = %d", gpio_get_value(gpio)); + printk(BIOS_INFO, "\n"); + } +} diff --git a/src/cpu/samsung/exynos5-common/gpio.h b/src/cpu/samsung/exynos5-common/gpio.h index d291fae..0de53f6 100644 --- a/src/cpu/samsung/exynos5-common/gpio.h +++ b/src/cpu/samsung/exynos5-common/gpio.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010 Samsung Electronics + * (C) Copyright 2009-2010 Samsung Electronics * Minkyu Kang mk7.kang@samsung.com * * This program is free software; you can redistribute it and/or @@ -22,10 +22,9 @@ #define __ASM_ARCH_COMMON_GPIO_H
#ifndef __ASSEMBLER__ /* FIXME: not needed (i hope)? */ -#include <cpu/samsung/s5p-common/gpio.h> -/* FIXME: s5p's gpio.h and exynos' gpio.h have a lot of conflicting - definitions */ -#if 0 + +#include <cpu/samsung/exynos5-common/cpu.h> /* FIXME: for S5PC110_GPIO_BASE */ + struct s5p_gpio_bank { unsigned int con; unsigned int dat; @@ -36,6 +35,99 @@ struct s5p_gpio_bank { unsigned char res1[8]; };
+struct s5pc100_gpio { + struct s5p_gpio_bank a0; + struct s5p_gpio_bank a1; + struct s5p_gpio_bank b; + struct s5p_gpio_bank c; + struct s5p_gpio_bank d; + struct s5p_gpio_bank e0; + struct s5p_gpio_bank e1; + struct s5p_gpio_bank f0; + struct s5p_gpio_bank f1; + struct s5p_gpio_bank f2; + struct s5p_gpio_bank f3; + struct s5p_gpio_bank g0; + struct s5p_gpio_bank g1; + struct s5p_gpio_bank g2; + struct s5p_gpio_bank g3; + struct s5p_gpio_bank i; + struct s5p_gpio_bank j0; + struct s5p_gpio_bank j1; + struct s5p_gpio_bank j2; + struct s5p_gpio_bank j3; + struct s5p_gpio_bank j4; + struct s5p_gpio_bank k0; + struct s5p_gpio_bank k1; + struct s5p_gpio_bank k2; + struct s5p_gpio_bank k3; + struct s5p_gpio_bank l0; + struct s5p_gpio_bank l1; + struct s5p_gpio_bank l2; + struct s5p_gpio_bank l3; + struct s5p_gpio_bank l4; + struct s5p_gpio_bank h0; + struct s5p_gpio_bank h1; + struct s5p_gpio_bank h2; + struct s5p_gpio_bank h3; +}; + +struct s5pc110_gpio { + struct s5p_gpio_bank a0; + struct s5p_gpio_bank a1; + struct s5p_gpio_bank b; + struct s5p_gpio_bank c0; + struct s5p_gpio_bank c1; + struct s5p_gpio_bank d0; + struct s5p_gpio_bank d1; + struct s5p_gpio_bank e0; + struct s5p_gpio_bank e1; + struct s5p_gpio_bank f0; + struct s5p_gpio_bank f1; + struct s5p_gpio_bank f2; + struct s5p_gpio_bank f3; + struct s5p_gpio_bank g0; + struct s5p_gpio_bank g1; + struct s5p_gpio_bank g2; + struct s5p_gpio_bank g3; + struct s5p_gpio_bank i; + struct s5p_gpio_bank j0; + struct s5p_gpio_bank j1; + struct s5p_gpio_bank j2; + struct s5p_gpio_bank j3; + struct s5p_gpio_bank j4; + struct s5p_gpio_bank mp0_1; + struct s5p_gpio_bank mp0_2; + struct s5p_gpio_bank mp0_3; + struct s5p_gpio_bank mp0_4; + struct s5p_gpio_bank mp0_5; + struct s5p_gpio_bank mp0_6; + struct s5p_gpio_bank mp0_7; + struct s5p_gpio_bank mp1_0; + struct s5p_gpio_bank mp1_1; + struct s5p_gpio_bank mp1_2; + struct s5p_gpio_bank mp1_3; + struct s5p_gpio_bank mp1_4; + struct s5p_gpio_bank mp1_5; + struct s5p_gpio_bank mp1_6; + struct s5p_gpio_bank mp1_7; + struct s5p_gpio_bank mp1_8; + struct s5p_gpio_bank mp2_0; + struct s5p_gpio_bank mp2_1; + struct s5p_gpio_bank mp2_2; + struct s5p_gpio_bank mp2_3; + struct s5p_gpio_bank mp2_4; + struct s5p_gpio_bank mp2_5; + struct s5p_gpio_bank mp2_6; + struct s5p_gpio_bank mp2_7; + struct s5p_gpio_bank mp2_8; + struct s5p_gpio_bank res1[48]; + struct s5p_gpio_bank h0; + struct s5p_gpio_bank h1; + struct s5p_gpio_bank h2; + struct s5p_gpio_bank h3; +}; + /* functions */ void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en); @@ -45,13 +137,65 @@ unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio); void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); -#endif
/* GPIO pins per bank */ #define GPIO_PER_BANK 8
+static inline unsigned int s5p_gpio_base(int nr) +{ + return S5PC110_GPIO_BASE; +} + +#define s5pc110_gpio_get_nr(bank, pin) \ + ((((((unsigned int)&(((struct s5pc110_gpio *)S5PC110_GPIO_BASE)->bank))\ + - S5PC110_GPIO_BASE) / sizeof(struct s5p_gpio_bank)) \ + * GPIO_PER_BANK) + pin) +#endif + +/* Pin configurations */ +#define GPIO_INPUT 0x0 +#define GPIO_OUTPUT 0x1 +#define GPIO_IRQ 0xf +#define GPIO_FUNC(x) (x) + +/* Pull mode */ +#define GPIO_PULL_NONE 0x0 +#define GPIO_PULL_DOWN 0x1 +#define GPIO_PULL_UP 0x2 + +/* Drive Strength level */ +#define GPIO_DRV_1X 0x0 +#define GPIO_DRV_3X 0x1 +#define GPIO_DRV_2X 0x2 +#define GPIO_DRV_4X 0x3 +#define GPIO_DRV_FAST 0x0 +#define GPIO_DRV_SLOW 0x1 + +#if 0 +struct s5p_gpio_bank { + unsigned int con; + unsigned int dat; + unsigned int pull; + unsigned int drv; + unsigned int pdn_con; + unsigned int pdn_pull; + unsigned char res1[8]; +}; + +/* functions */ +void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); +void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en); +void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio); +void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en); +unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio); +void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); +void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); +void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); #endif
+/* GPIO pins per bank */ +#define GPIO_PER_BANK 8 + /* Pin configurations */ #define EXYNOS_GPIO_INPUT 0x0 #define EXYNOS_GPIO_OUTPUT 0x1 diff --git a/src/cpu/samsung/exynos5-common/i2c.c b/src/cpu/samsung/exynos5-common/i2c.c new file mode 100644 index 0000000..624d48b --- /dev/null +++ b/src/cpu/samsung/exynos5-common/i2c.c @@ -0,0 +1,612 @@ +/* + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * 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 + */ + +/* This code should work for both the S3C2400 and the S3C2410 + * as they seem to have the same I2C controller inside. + * The different address mapping is handled by the s3c24xx.h files below. + */ + +#include <common.h> +#include <arch/io.h> +#include "clk.h" +#include "cpu/samsung/exynos5-common/clk.h" +#include "cpu/samsung/exynos5250/cpu.h" +#include "gpio.h" +#include "cpu/samsung/exynos5250/gpio.h" +#include "cpu/samsung/exynos5250/pinmux.h" + +//#include <fdtdec.h> +#include "device/i2c.h" +#include "i2c.h" + +#define I2C_WRITE 0 +#define I2C_READ 1 + +#define I2C_OK 0 +#define I2C_NOK 1 +#define I2C_NACK 2 +#define I2C_NOK_LA 3 /* Lost arbitration */ +#define I2C_NOK_TOUT 4 /* time out */ + +#define I2CSTAT_BSY 0x20 /* Busy bit */ +#define I2CSTAT_NACK 0x01 /* Nack bit */ +#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ +#define I2CCON_IRPND 0x10 /* Interrupt pending bit */ +#define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ +#define I2C_MODE_MR 0x80 /* Master Receive Mode */ +#define I2C_START_STOP 0x20 /* START / STOP */ +#define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */ + +/* The timeouts we live by */ +enum { + I2C_XFER_TIMEOUT_MS = 35, /* xfer to complete */ + I2C_INIT_TIMEOUT_MS = 1000, /* bus free on init */ + I2C_IDLE_TIMEOUT_MS = 100, /* waiting for bus idle */ + I2C_STOP_TIMEOUT_US = 200, /* waiting for stop events */ +}; + +/* We should not rely on any particular ordering of these IDs */ +#if 0 +#ifndef CONFIG_OF_CONTROL +static enum periph_id periph_for_dev[EXYNOS_I2C_MAX_CONTROLLERS] = { + PERIPH_ID_I2C0, + PERIPH_ID_I2C1, + PERIPH_ID_I2C2, + PERIPH_ID_I2C3, + PERIPH_ID_I2C4, + PERIPH_ID_I2C5, + PERIPH_ID_I2C6, + PERIPH_ID_I2C7, +}; +#endif +#endif + +static unsigned int g_current_bus __attribute__((section(".data"))); +static struct s3c24x0_i2c *g_early_i2c_config __attribute__((section(".data"))); + +static struct s3c24x0_i2c_bus i2c_bus[EXYNOS_I2C_MAX_CONTROLLERS] + __attribute__((section(".data"))); +static int i2c_busses __attribute__((section(".data"))); + +void i2c_set_early_reg(unsigned int base) +{ + g_early_i2c_config = (struct s3c24x0_i2c *)base; +} + +static struct s3c24x0_i2c_bus *get_bus(int bus_idx) +{ + /* If an early i2c config exists we just use that */ + if (g_early_i2c_config) { + /* FIXME: value not retained from i2c_set_early_reg()? (but then, how + * did if (!i2c) check pass earlier on? Corrupt value? */ + i2c_bus[0].regs = g_early_i2c_config; + return &i2c_bus[0]; + } + + if (bus_idx < i2c_busses) + return &i2c_bus[bus_idx]; + debug("Undefined bus: %d\n", bus_idx); + return NULL; +} + +static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void) +{ + return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE); +} + +static int WaitForXfer(struct s3c24x0_i2c *i2c) +{ + int i; + + i = I2C_XFER_TIMEOUT_MS * 20; + while (!(readl(&i2c->iiccon) & I2CCON_IRPND)) { + if (i == 0) { + debug("%s: i2c xfer timeout\n", __func__); + return I2C_NOK_TOUT; + } + udelay(50); + i--; + } + + return I2C_OK; +} + +static int IsACK(struct s3c24x0_i2c *i2c) +{ + return !(readl(&i2c->iicstat) & I2CSTAT_NACK); +} + +static void ReadWriteByte(struct s3c24x0_i2c *i2c) +{ + uint32_t x; + + x = readl(&i2c->iiccon); + writel(x & ~I2CCON_IRPND, &i2c->iiccon); + /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ +// writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); +} + +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) +{ + ulong freq, pres = 16, div; + + freq = clock_get_periph_rate(PERIPH_ID_I2C0); + /* calculate prescaler and divisor values */ + if ((freq / pres / (16 + 1)) > speed) + /* set prescaler to 512 */ + pres = 512; + + div = 0; + + while ((freq / pres / (div + 1)) > speed) + div++; + + /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ + writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); + + /* init to SLAVE REVEIVE and set slaveaddr */ + writel(0, &i2c->iicstat); + writel(slaveadd, &i2c->iicadd); + /* program Master Transmit (and implicit STOP) */ + writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); +} + +/* TODO: determine if this is necessary to init board using FDT-provided info */ +#if 0 +void board_i2c_init(const void *blob) +{ + /* + * Turn off the early i2c configuration and init the i2c properly, + * this is done here to enable the use of i2c configs from FDT. + */ + i2c_set_early_reg(0); + +#ifdef CONFIG_OF_CONTROL + int node_list[EXYNOS_I2C_MAX_CONTROLLERS]; + int i, count; + + count = fdtdec_find_aliases_for_id(blob, "i2c", + COMPAT_SAMSUNG_S3C2440_I2C, node_list, + EXYNOS_I2C_MAX_CONTROLLERS); + + for (i = 0; i < count; i++) { + struct s3c24x0_i2c_bus *bus; + int node = node_list[i]; + + if (node < 0) + continue; + bus = &i2c_bus[i2c_busses]; + bus->regs = (struct s3c24x0_i2c *) + fdtdec_get_addr(blob, node, "reg"); + bus->id = (enum periph_id) + fdtdec_get_int(blob, node, "samsung,periph-id", -1); + bus->node = node; + bus->bus_num = i2c_busses++; + } +#else + int i; + + for (i = 0; i < EXYNOS_I2C_MAX_CONTROLLERS; i++) { + uintptr_t reg_addr = samsung_get_base_i2c() + + EXYNOS_I2C_SPACING * i; + + i2c_bus[i].regs = (struct s3c24x0_i2c_bus *)reg_addr; + i2c_bus[i].id = periph_for_dev[i]; + } + i2c_busses = EXYNOS_I2C_MAX_CONTROLLERS; +#endif +} +#endif + +/* + * MULTI BUS I2C support + */ +static void i2c_bus_init(struct s3c24x0_i2c_bus *i2c, unsigned int bus) +{ + exynos_pinmux_config(i2c->id, 0); + i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +} + +#ifdef CONFIG_I2C_MULTI_BUS +int i2c_set_bus_num(unsigned int bus) +{ + struct s3c24x0_i2c_bus *i2c; + + i2c = get_bus(bus); + if (!i2c) + return -1; + g_current_bus = bus; + i2c_bus_init(i2c, g_current_bus); + + return 0; +} + +unsigned int i2c_get_bus_num(void) +{ + return g_current_bus; +} +#endif + +#ifdef CONFIG_OF_CONTROL +int i2c_get_bus_num_fdt(const void *blob, int node) +{ + enum fdt_compat_id compat; + fdt_addr_t reg; + int i; + + compat = fdtdec_lookup(blob, node); + if (compat != COMPAT_SAMSUNG_S3C2440_I2C) { + debug("%s: Not a supported I2C node\n", __func__); + return -1; + } + + reg = fdtdec_get_addr(blob, node, "reg"); + for (i = 0; i < i2c_busses; i++) + if (reg == (fdt_addr_t)(uintptr_t)i2c_bus[i].regs) + return i; + + debug("%s: Can't find any matched I2C bus\n", __func__); + return -1; +} + +int i2c_reset_port_fdt(const void *blob, int node) +{ + struct s3c24x0_i2c_bus *i2c; + + int bus; + + bus = i2c_get_bus_num_fdt(blob, node); + if (bus < 0) { + printf("could not get bus for node %d\n", node); + return -1; + } + i2c = get_bus(bus); + if (!i2c) { + printf("get_bus() failed for node node %d\n", node); + return -1; + } + + i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + return 0; +} +#endif + +/* + * Verify the whether I2C ACK was received or not + * + * @param i2c pointer to I2C register base + * @param buf array of data + * @param len length of data + * return I2C_OK when transmission done + * I2C_NACK otherwise + */ +static int i2c_send_verify(struct s3c24x0_i2c *i2c, unsigned char buf[], + unsigned char len) +{ + int i, result = I2C_OK; + + if (IsACK(i2c)) { + for (i = 0; (i < len) && (result == I2C_OK); i++) { + writel(buf[i], &i2c->iicds); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + if (result == I2C_OK && !IsACK(i2c)) + result = I2C_NACK; + } + } else { + result = I2C_NACK; + } + + return result; +} + +void i2c_init(int speed, int slaveadd) +{ + struct s3c24x0_i2c_bus *i2c; + struct exynos5_gpio_part1 *gpio; + int i; + uint32_t x; + + /* By default i2c channel 0 is the current bus */ + g_current_bus = 0; + + i2c = get_bus(g_current_bus); + if (!i2c) + return; + + i2c_bus_init(i2c, g_current_bus); + + /* wait for some time to give previous transfer a chance to finish */ + i = I2C_INIT_TIMEOUT_MS * 20; + while ((readl(&i2c->regs->iicstat) & I2CSTAT_BSY) && (i > 0)) { + udelay(50); + i--; + } + + gpio = exynos_get_base_gpio1(); + /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ +// writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con); + x = readl(&gpio->b3.con); + writel((x & ~0x00FF) | 0x0022, &gpio->b3.con); + + i2c_ch_init(i2c->regs, speed, slaveadd); +} + +/* + * Send a STOP event and wait for it to have completed + * + * @param mode If it is a master transmitter or receiver + * @return I2C_OK if the line became idle before timeout I2C_NOK_TOUT otherwise + */ +static int i2c_send_stop(struct s3c24x0_i2c *i2c, int mode) +{ + int timeout; + + /* Setting the STOP event to fire */ + writel(mode | I2C_TXRX_ENA, &i2c->iicstat); + ReadWriteByte(i2c); + + /* Wait for the STOP to send and the bus to go idle */ + for (timeout = I2C_STOP_TIMEOUT_US; timeout > 0; timeout -= 5) { + if (!(readl(&i2c->iicstat) & I2CSTAT_BSY)) + return I2C_OK; + udelay(5); + } + + return I2C_NOK_TOUT; +} + +/* + * cmd_type is 0 for write, 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + */ +static int i2c_transfer(struct s3c24x0_i2c *i2c, + unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], + unsigned short data_len) +{ + int i, result, stop_bit_result; + uint32_t x; + + if (data == 0 || data_len == 0) { + /* Don't support data transfer of no length or to address 0 */ + debug("i2c_transfer: bad call\n"); + return I2C_NOK; + } + + /* Check I2C bus idle */ + i = I2C_IDLE_TIMEOUT_MS * 20; + while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) { + udelay(50); + i--; + } + + if (readl(&i2c->iicstat) & I2CSTAT_BSY) { + debug("%s: bus busy\n", __func__); + return I2C_NOK_TOUT; + } + + /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ + //writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); + x = readl(&i2c->iiccon); + writel(x | I2CCON_ACKGEN, &i2c->iiccon); + + if (addr && addr_len) { + writel(chip, &i2c->iicds); + /* send START */ + writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); + if (WaitForXfer(i2c) == I2C_OK) + result = i2c_send_verify(i2c, addr, addr_len); + else + result = I2C_NACK; + } else + result = I2C_NACK; + + switch (cmd_type) { + case I2C_WRITE: + if (result == I2C_OK) + result = i2c_send_verify(i2c, data, data_len); + else { + writel(chip, &i2c->iicds); + /* send START */ + writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); + if (WaitForXfer(i2c) == I2C_OK) + result = i2c_send_verify(i2c, data, data_len); + } + + if (result == I2C_OK) + result = WaitForXfer(i2c); + + stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MT); + break; + + case I2C_READ: + { + int was_ok = (result == I2C_OK); + + writel(chip, &i2c->iicds); + /* resend START */ + writel(I2C_MODE_MR | I2C_TXRX_ENA | + I2C_START_STOP, &i2c->iicstat); + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + + if (was_ok || IsACK(i2c)) { + i = 0; + while ((i < data_len) && (result == I2C_OK)) { + /* disable ACK for final READ */ + if (i == data_len - 1) { + /* FIXME(dhendrix): nested macro */ +#if 0 + writel(readl(&i2c->iiccon) & + ~I2CCON_ACKGEN, + &i2c->iiccon); +#endif + x = readl(&i2c->iiccon) & ~I2CCON_ACKGEN; + writel(x, &i2c->iiccon); + } + ReadWriteByte(i2c); + result = WaitForXfer(i2c); + data[i] = readl(&i2c->iicds); + i++; + } + } else { + result = I2C_NACK; + } + + stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MR); + break; + } + + default: + debug("i2c_transfer: bad call\n"); + result = stop_bit_result = I2C_NOK; + break; + } + + /* + * If the transmission went fine, then only the stop bit was left to + * fail. Otherwise, the real failure we're interested in came before + * that, during the actual transmission. + */ + return (result == I2C_OK) ? stop_bit_result : result; +} + +int i2c_probe(uchar chip) +{ + struct s3c24x0_i2c_bus *i2c; + uchar buf[1]; + int ret; + + i2c = get_bus(g_current_bus); + if (!i2c) + return -1; + buf[0] = 0; + + /* + * What is needed is to send the chip address and verify that the + * address was <ACK>ed (i.e. there was a chip at that address which + * drove the data line low). + */ + ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, 0, 0, buf, 1); + + return ret != I2C_OK; +} + +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + struct s3c24x0_i2c_bus *i2c; + uchar xaddr[4]; + int ret; + + if (alen > 4) { + debug("I2C read: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } + +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + i2c = get_bus(g_current_bus); + if (!i2c) + return -1; + ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, &xaddr[4 - alen], + alen, buffer, len); + if (ret) { + debug("I2c read: failed %d\n", ret); + return 1; + } + return 0; +} + +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + struct s3c24x0_i2c_bus *i2c; + uchar xaddr[4]; + int ret; + + if (alen > 4) { + debug("I2C write: addr len %d not supported\n", alen); + return 1; + } + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if (alen > 0) + chip |= ((addr >> (alen * 8)) & + CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +#endif + i2c = get_bus(g_current_bus); + if (!i2c) + return -1; + + ret = i2c_transfer(i2c->regs, I2C_WRITE, chip << 1, &xaddr[4 - alen], + alen, buffer, len); + + return ret != 0; +} diff --git a/src/cpu/samsung/exynos5-common/i2c.h b/src/cpu/samsung/exynos5-common/i2c.h new file mode 100644 index 0000000..eb68af7 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/i2c.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 + */ + +#ifndef _S3C24X0_I2C_H +#define _S3C24X0_I2C_H + +/* FIXME: gross hack */ +#include "cpu/samsung/exynos5250/periph.h" + +struct s3c24x0_i2c { + u32 iiccon; + u32 iicstat; + u32 iicadd; + u32 iicds; + u32 iiclc; +}; + +struct s3c24x0_i2c_bus { + int node; /* device tree node */ + int bus_num; /* i2c bus number */ + struct s3c24x0_i2c *regs; + enum periph_id id; +}; +#endif /* _S3C24X0_I2C_H */ diff --git a/src/cpu/samsung/exynos5-common/power.h b/src/cpu/samsung/exynos5-common/power.h new file mode 100644 index 0000000..57e2a2b --- /dev/null +++ b/src/cpu/samsung/exynos5-common/power.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009 Samsung Electronics + * Kyungmin Park kyungmin.park@samsung.com + * Minkyu Kang mk7.kang@samsung.com + * + * 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_POWER_H_ +#define __ASM_ARM_ARCH_POWER_H_ + +/* + * Power control + */ +#define S5PC100_OTHERS 0xE0108200 +#define S5PC100_RST_STAT 0xE0108300 +#define S5PC100_SLEEP_WAKEUP (1 << 3) +#define S5PC100_WAKEUP_STAT 0xE0108304 +#define S5PC100_INFORM0 0xE0108400 + +#define S5PC110_RST_STAT 0xE010A000 +#define S5PC110_SLEEP_WAKEUP (1 << 3) +#define S5PC110_WAKEUP_STAT 0xE010C200 +#define S5PC110_OTHERS 0xE010E000 +#define S5PC110_USB_PHY_CON 0xE010E80C +#define S5PC110_INFORM0 0xE010F000 + +#endif diff --git a/src/cpu/samsung/exynos5-common/pwm.c b/src/cpu/samsung/exynos5-common/pwm.c new file mode 100644 index 0000000..f7c1fb1 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/pwm.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * + * Donghwa Lee dh09.lee@samsung.com + * + * 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 <common.h> +#include <arch/io.h> +#include <cpu/samsung/exynos5-common/clk.h> +#include <cpu/samsung/exynos5250/cpu.h> +#include <cpu/samsung/exynos5250/periph.h> +#include <cpu/samsung/exynos5-common/pwm.h> + +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; +} + +int pwm_check_enabled(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + const unsigned long tcon = readl(&pwm->tcon); + + return tcon & TCON_START(pwm_id); +} + +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 = 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) +{ + 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 -1; +// return -ERANGE; + + if (duty_ns > period_ns) + return -1; +// 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 = 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/exynos5-common/pwm.h b/src/cpu/samsung/exynos5-common/pwm.h index a4e0acf..d7aa76f 100644 --- a/src/cpu/samsung/exynos5-common/pwm.h +++ b/src/cpu/samsung/exynos5-common/pwm.h @@ -63,6 +63,12 @@ struct s5p_timer { 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 /* __ASSEMBLER__ */
#endif diff --git a/src/cpu/samsung/exynos5-common/sromc.c b/src/cpu/samsung/exynos5-common/sromc.c new file mode 100644 index 0000000..091e8d1 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/sromc.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Samsung Electronics + * Naveen Krishna Ch ch.naveen@samsung.com + * + * 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 <common.h> +#include <asm/io.h> +#include <asm/arch/sromc.h> + +/* + * s5p_config_sromc() - select the proper SROMC Bank and configure the + * band width control and bank control registers + * srom_bank - SROM + * srom_bw_conf - SMC Band witdh reg configuration value + * srom_bc_conf - SMC Bank Control reg configuration value + */ +void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf) +{ + u32 tmp; + struct s5p_sromc *srom = + (struct s5p_sromc *)samsung_get_base_sromc(); + + /* Configure SMC_BW register to handle proper SROMC bank */ + tmp = srom->bw; + tmp &= ~(0xF << (srom_bank * 4)); + tmp |= srom_bw_conf; + srom->bw = tmp; + + /* Configure SMC_BC register */ + srom->bc[srom_bank] = srom_bc_conf; +} diff --git a/src/cpu/samsung/exynos5-common/timer.c b/src/cpu/samsung/exynos5-common/timer.c new file mode 100644 index 0000000..7e918aa --- /dev/null +++ b/src/cpu/samsung/exynos5-common/timer.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Heungjun Kim riverful.kim@samsung.com + * Inki Dae inki.dae@samsung.com + * Minkyu Kang mk7.kang@samsung.com + * + * 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 <common.h> +#include <arch/io.h> +#include <cpu/samsung/exynos5-common/pwm.h> +#include <cpu/samsung/exynos5-common/clk.h> +#include <cpu/samsung/exynos5250/cpu.h> +#include <cpu/samsung/exynos5-common/exynos5-common.h> + +//#include <pwm.h> + +//DECLARE_GLOBAL_DATA_PTR; +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 (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 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 */ + //gd->timer_reset_value = 0; + timer_reset_value = 0; + + /* Use this as the last timer value we saw */ + //gd->lastinc = timer_get_us_down(); + lastinc = timer_get_us_down(); + } + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long get_timer(unsigned long base) +{ + 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. + */ +#if 0 + gd->timer_reset_value += gd->lastinc - now; + gd->lastinc = now; + + /* Divide by 1000 to convert from us to ms */ + return gd->timer_reset_value / 1000 - base; +#endif + timer_reset_value += lastinc - now; + lastinc = now; + + /* Divide by 1000 to convert from us to ms */ + return timer_reset_value / 1000 - base; +} + +unsigned long timer_get_us(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + unsigned long now_downward_us = readl(&timer->tcnto4); + + /* + * Note that this timer counts downward. The pre-SPL process (BL1) + * takes about 100ms, so add this in here. + */ + return CONFIG_SPL_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) + ; +} + +/* + * 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; +} + +unsigned long timer_get_boot_us(void) +{ + return timer_get_us(); +} diff --git a/src/cpu/samsung/exynos5-common/watchdog.h b/src/cpu/samsung/exynos5-common/watchdog.h new file mode 100644 index 0000000..5b3b651 --- /dev/null +++ b/src/cpu/samsung/exynos5-common/watchdog.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * Heungjun Kim riverful.kim@samsung.com + * + * 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 + */ + +#ifndef __ASM_ARM_ARCH_COMMON_WATCHDOG_H_ +#define __ASM_ARM_ARCH_COMMON_WATCHDOG_H_ + +#define WTCON_RESET_OFFSET 0 +#define WTCON_INTEN_OFFSET 2 +#define WTCON_CLKSEL_OFFSET 3 +#define WTCON_EN_OFFSET 5 +#define WTCON_PRE_OFFSET 8 + +#define WTCON_CLK_16 0x0 +#define WTCON_CLK_32 0x1 +#define WTCON_CLK_64 0x2 +#define WTCON_CLK_128 0x3 + +#define WTCON_CLK(x) ((x & 0x3) << WTCON_CLKSEL_OFFSET) +#define WTCON_PRESCALER(x) ((x) << WTCON_PRE_OFFSET) +#define WTCON_EN (0x1 << WTCON_EN_OFFSET) +#define WTCON_RESET (0x1 << WTCON_RESET_OFFSET) +#define WTCON_INT (0x1 << WTCON_INTEN_OFFSET) + +#ifndef __ASSEMBLER__ +struct s5p_watchdog { + unsigned int wtcon; + unsigned int wtdat; + unsigned int wtcnt; + unsigned int wtclrint; +}; + +/* functions */ +void wdt_stop(void); +void wdt_start(unsigned int timeout); +#endif /* __ASSEMBLER__ */ + +#endif diff --git a/src/cpu/samsung/exynos5-common/wdt.c b/src/cpu/samsung/exynos5-common/wdt.c new file mode 100644 index 0000000..94acc1e --- /dev/null +++ b/src/cpu/samsung/exynos5-common/wdt.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Minkyu Kang mk7.kang@samsung.com + * + * 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 <common.h> +#include <asm/io.h> +#include <asm/arch/watchdog.h> + +#define PRESCALER_VAL 255 + +void wdt_stop(void) +{ + struct s5p_watchdog *wdt = + (struct s5p_watchdog *)samsung_get_base_watchdog(); + unsigned int wtcon; + + wtcon = readl(&wdt->wtcon); + wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET); + + writel(wtcon, &wdt->wtcon); +} + +void wdt_start(unsigned int timeout) +{ + struct s5p_watchdog *wdt = + (struct s5p_watchdog *)samsung_get_base_watchdog(); + unsigned int wtcon; + + wdt_stop(); + + wtcon = readl(&wdt->wtcon); + wtcon |= (WTCON_EN | WTCON_CLK(WTCON_CLK_128)); + wtcon &= ~WTCON_INT; + wtcon |= WTCON_RESET; + wtcon |= WTCON_PRESCALER(PRESCALER_VAL); + + writel(timeout, &wdt->wtdat); + writel(timeout, &wdt->wtcnt); + writel(wtcon, &wdt->wtcon); +} diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc index ec6b0e1..10c071a 100644 --- a/src/cpu/samsung/exynos5250/Makefile.inc +++ b/src/cpu/samsung/exynos5250/Makefile.inc @@ -12,7 +12,7 @@ bootblock-$(CONFIG_EARLY_CONSOLE) += uart.c
romstage-y += clock.c romstage-y += clock_init.c -romstage-y += pinmux.c # required by s3c24x0_i2c (s5p-common) and uart. +romstage-y += pinmux.c # required by s3c24x0_i2c (exynos5-common) and uart. romstage-y += exynos_cache.c romstage-y += dmc_common.c romstage-y += dmc_init_ddr3.c diff --git a/src/cpu/samsung/exynos5250/clock.c b/src/cpu/samsung/exynos5250/clock.c index fc01387..115d40d 100644 --- a/src/cpu/samsung/exynos5250/clock.c +++ b/src/cpu/samsung/exynos5250/clock.c @@ -29,7 +29,7 @@ #include <cpu/samsung/exynos5250/clk.h> #include <cpu/samsung/exynos5250/clock_init.h> #include <cpu/samsung/exynos5250/cpu.h> -#include <cpu/samsung/s5p-common/clk.h> +#include <cpu/samsung/exynos5-common/clk.h>
/* input clock of PLL: SMDK5250 has 24MHz input clock */ #define CONFIG_SYS_CLK_FREQ 24000000 diff --git a/src/cpu/samsung/exynos5250/clock_init.c b/src/cpu/samsung/exynos5250/clock_init.c index 27e96ae..618fdb6 100644 --- a/src/cpu/samsung/exynos5250/clock_init.c +++ b/src/cpu/samsung/exynos5250/clock_init.c @@ -35,7 +35,7 @@ #include <cpu/samsung/exynos5250/cpu.h> #include <cpu/samsung/exynos5250/dmc.h> #include <cpu/samsung/exynos5250/s5p-dp.h> -#include <cpu/samsung/s5p-common/clk.h> +#include <cpu/samsung/exynos5-common/clk.h>
#include "setup.h"
diff --git a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c index 541f749..9a4ead0 100644 --- a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c +++ b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c @@ -27,7 +27,7 @@ #include <console/console.h> //#include "clock.h" /* FIXME(dhendrix): untangle clock/clk ... */ -#include <cpu/samsung/s5p-common/clock.h> +#include <cpu/samsung/exynos5-common/clock.h> #include <system.h> #include "clk.h" #include "cpu.h" diff --git a/src/cpu/samsung/exynos5250/power.c b/src/cpu/samsung/exynos5250/power.c index d0650fb..41e1e1b 100644 --- a/src/cpu/samsung/exynos5250/power.c +++ b/src/cpu/samsung/exynos5250/power.c @@ -33,7 +33,7 @@ #include <drivers/maxim/max77686/max77686.h>
#include "device/i2c.h" -#include "cpu/samsung/s5p-common/s3c24x0_i2c.h" +#include "cpu/samsung/exynos5-common/i2c.h"
static void ps_hold_setup(void) { diff --git a/src/cpu/samsung/s5p-common/Makefile.inc b/src/cpu/samsung/s5p-common/Makefile.inc deleted file mode 100644 index 118dd47..0000000 --- a/src/cpu/samsung/s5p-common/Makefile.inc +++ /dev/null @@ -1,17 +0,0 @@ -bootblock-y += s5p_gpio.c -bootblock-$(CONFIG_EARLY_CONSOLE) += pwm.c -bootblock-$(CONFIG_EARLY_CONSOLE) += timer.c - -romstage-y += pwm.c # needed by timer.c -romstage-y += s5p_gpio.c -romstage-y += timer.c -romstage-y += s3c24x0_i2c.c - -#romstage-y += sromc.c -#romstage-y += wdt.c - -ramstage-y += cpu_info.c -ramstage-y += pwm.c # needed by timer.c -ramstage-y += timer.c -ramstage-y += s5p_gpio.c -ramstage-y += s3c24x0_i2c.c diff --git a/src/cpu/samsung/s5p-common/clk.h b/src/cpu/samsung/s5p-common/clk.h deleted file mode 100644 index 69c7e4e..0000000 --- a/src/cpu/samsung/s5p-common/clk.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * Heungjun Kim riverful.kim@samsung.com - * - * 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 __S5P_COMMON_CLK_H_ -#define __S5P_COMMON_CLK_H_ - -#define APLL 0 -#define MPLL 1 -#define EPLL 2 -#define HPLL 3 -#define VPLL 4 - -unsigned long get_pll_clk(int pllreg); -unsigned long get_arm_clk(void); -unsigned long get_pwm_clk(void); -unsigned long get_uart_clk(int dev_index); -void set_mmc_clk(int dev_index, unsigned int div); - -#endif diff --git a/src/cpu/samsung/s5p-common/clock.h b/src/cpu/samsung/s5p-common/clock.h deleted file mode 100644 index c0cd896..0000000 --- a/src/cpu/samsung/s5p-common/clock.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * Heungjun Kim riverful.kim@samsung.com - * - * 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_CLOCK_H_ -#define __ASM_ARM_ARCH_CLOCK_H_ - -#ifndef __ASSEMBLER__ -struct s5pc100_clock { - unsigned int apll_lock; - unsigned int mpll_lock; - unsigned int epll_lock; - unsigned int hpll_lock; - unsigned char res1[0xf0]; - unsigned int apll_con; - unsigned int mpll_con; - unsigned int epll_con; - unsigned int hpll_con; - unsigned char res2[0xf0]; - unsigned int src0; - unsigned int src1; - unsigned int src2; - unsigned int src3; - unsigned char res3[0xf0]; - unsigned int div0; - unsigned int div1; - unsigned int div2; - unsigned int div3; - unsigned int div4; - unsigned char res4[0x1ec]; - unsigned int gate_d00; - unsigned int gate_d01; - unsigned int gate_d02; - unsigned char res5[0x54]; - unsigned int gate_sclk0; - unsigned int gate_sclk1; -}; - -struct s5pc110_clock { - unsigned int apll_lock; - unsigned char res1[0x4]; - unsigned int mpll_lock; - unsigned char res2[0x4]; - unsigned int epll_lock; - unsigned char res3[0xc]; - unsigned int vpll_lock; - unsigned char res4[0xdc]; - unsigned int apll_con; - unsigned char res5[0x4]; - unsigned int mpll_con; - unsigned char res6[0x4]; - unsigned int epll_con; - unsigned char res7[0xc]; - unsigned int vpll_con; - unsigned char res8[0xdc]; - unsigned int src0; - unsigned int src1; - unsigned int src2; - unsigned int src3; - unsigned char res9[0xf0]; - unsigned int div0; - unsigned int div1; - unsigned int div2; - unsigned int div3; - unsigned int div4; - unsigned char res10[0x1ec]; - unsigned int gate_d00; - unsigned int gate_d01; - unsigned int gate_d02; - unsigned char res11[0x54]; - unsigned int gate_sclk0; - unsigned int gate_sclk1; -}; -#endif - -#endif diff --git a/src/cpu/samsung/s5p-common/cpu.h b/src/cpu/samsung/s5p-common/cpu.h deleted file mode 100644 index 34be1f2..0000000 --- a/src/cpu/samsung/s5p-common/cpu.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * Heungjun Kim riverful.kim@samsung.com - * - * 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 _S5PC1XX_CPU_H -#define _S5PC1XX_CPU_H - -#define S5PC1XX_ADDR_BASE 0xE0000000 - -/* S5PC100 */ -#define S5PC100_PRO_ID 0xE0000000 -#define S5PC100_CLOCK_BASE 0xE0100000 -#define S5PC100_GPIO_BASE 0xE0300000 -#define S5PC100_VIC0_BASE 0xE4000000 -#define S5PC100_VIC1_BASE 0xE4100000 -#define S5PC100_VIC2_BASE 0xE4200000 -#define S5PC100_DMC_BASE 0xE6000000 -#define S5PC100_SROMC_BASE 0xE7000000 -#define S5PC100_ONENAND_BASE 0xE7100000 -#define S5PC100_PWMTIMER_BASE 0xEA000000 -#define S5PC100_WATCHDOG_BASE 0xEA200000 -#define S5PC100_UART_BASE 0xEC000000 -#define S5PC100_MMC_BASE 0xED800000 - -/* S5PC110 */ -#define S5PC110_PRO_ID 0xE0000000 -#define S5PC110_CLOCK_BASE 0xE0100000 -#define S5PC110_GPIO_BASE 0xE0200000 -#define S5PC110_PWMTIMER_BASE 0xE2500000 -#define S5PC110_WATCHDOG_BASE 0xE2700000 -#define S5PC110_UART_BASE 0xE2900000 -#define S5PC110_SROMC_BASE 0xE8000000 -#define S5PC110_MMC_BASE 0xEB000000 -#define S5PC110_DMC0_BASE 0xF0000000 -#define S5PC110_DMC1_BASE 0xF1400000 -#define S5PC110_VIC0_BASE 0xF2000000 -#define S5PC110_VIC1_BASE 0xF2100000 -#define S5PC110_VIC2_BASE 0xF2200000 -#define S5PC110_VIC3_BASE 0xF2300000 -#define S5PC110_OTG_BASE 0xEC000000 -#define S5PC110_PHY_BASE 0xEC100000 -#define S5PC110_USB_PHY_CONTROL 0xE010E80C - - -#include <arch/io.h> -/* CPU detection macros */ -extern unsigned int s5p_cpu_id; - -/* FIXME(dhendrix): conflicts with the one in cpu_info.c ... */ -#if 0 -inline void s5p_set_cpu_id(void) -{ - s5p_cpu_id = readl(S5PC100_PRO_ID); - s5p_cpu_id = 0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12); -} -#endif -inline void s5p_set_cpu_id(void); - -#define IS_SAMSUNG_TYPE(type, id) \ -static inline int cpu_is_##type(void) \ -{ \ - return s5p_cpu_id == id ? 1 : 0; \ -} - -IS_SAMSUNG_TYPE(s5pc100, 0xc100) -IS_SAMSUNG_TYPE(s5pc110, 0xc110) - -/* - * FIXME(dhendrix): collides with SAMSUNG_BASE in exynos header files. We - * don't really care about old S5P processors right now. - */ -#if 0 -#define SAMSUNG_BASE(device, base) \ -static inline unsigned int samsung_get_base_##device(void) \ -{ \ - if (cpu_is_s5pc100()) \ - return S5PC100_##base; \ - else if (cpu_is_s5pc110()) \ - return S5PC110_##base; \ - else \ - return 0; \ -} - -SAMSUNG_BASE(clock, CLOCK_BASE) -SAMSUNG_BASE(gpio, GPIO_BASE) -SAMSUNG_BASE(pro_id, PRO_ID) -SAMSUNG_BASE(mmc, MMC_BASE) -SAMSUNG_BASE(sromc, SROMC_BASE) -SAMSUNG_BASE(timer, PWMTIMER_BASE) -SAMSUNG_BASE(uart, UART_BASE) -SAMSUNG_BASE(watchdog, WATCHDOG_BASE) -#endif - -int s5p_get_cpu_rev(void); -//void s5p_set_cpu_id(void); -int s5p_get_cpu_id(void); - -#endif /* _S5PC1XX_CPU_H */ diff --git a/src/cpu/samsung/s5p-common/cpu_info.c b/src/cpu/samsung/s5p-common/cpu_info.c deleted file mode 100644 index 1c4c49f..0000000 --- a/src/cpu/samsung/s5p-common/cpu_info.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * - * 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 <common.h> -#if 0 -#include <asm/io.h> -#include <asm/arch/clk.h> -#include <asm/arch/clock.h> -#include <asm/arch/dmc.h> -#endif -#include <arch/io.h> - -#include <cpu/samsung/s5p-common/clk.h> -#include <cpu/samsung/s5p-common/clock.h> -#include <cpu/samsung/s5p-common/cpu.h> - -#include <cpu/samsung/exynos5250/dmc.h> -#include <cpu/samsung/exynos5-common/cpu.h> /* for EXYNOS_PRO_ID */ - -/* FIXME(dhendrix): consolidate samsung ID code/#defines to a common location */ -#include <cpu/samsung/exynos5250/setup.h> /* cpu_info_init() prototype */ - -/* - * The following CPU infos are initialized in lowlevel_init(). They should be - * put in the .data section. Otherwise, a compile will put them in the .bss - * section since they don't have initial values. The relocation code which - * runs after lowlevel_init() will reset them to zero. - */ -unsigned int s5p_cpu_id __attribute__((section(".data"))); -unsigned int s5p_cpu_rev __attribute__((section(".data"))); - -void cpu_info_init(void) -{ - s5p_set_cpu_id(); -} - -int s5p_get_cpu_id(void) -{ - return s5p_cpu_id; -} - -int s5p_get_cpu_rev(void) -{ - return s5p_cpu_rev; -} - -void s5p_set_cpu_id(void) -{ - s5p_cpu_id = readl(EXYNOS_PRO_ID); - s5p_cpu_id = (0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12)); - - /* - * 0xC200: EXYNOS4210 EVT0 - * 0xC210: EXYNOS4210 EVT1 - */ - if (s5p_cpu_id == 0xC200) { - s5p_cpu_id |= 0x10; - s5p_cpu_rev = 0; - } else if (s5p_cpu_id == 0xC210) { - s5p_cpu_rev = 1; - } -} - -#ifdef CONFIG_DISPLAY_CPUINFO -int print_cpuinfo(void) -{ - char buf[32]; - - printf("CPU: S5P%X @ %sMHz\n", - s5p_cpu_id, strmhz(buf, get_arm_clk())); - - return 0; -} -#endif - -#if 0 -void board_show_dram(ulong size) -{ - enum ddr_mode mem_type; - unsigned frequency_mhz; - unsigned arm_freq; - enum mem_manuf mem_manuf; - char buf[32]; - int ret; - - /* Get settings from the fdt */ - ret = clock_get_mem_selection(&mem_type, &frequency_mhz, - &arm_freq, &mem_manuf); - if (ret) - panic("Invalid DRAM information"); - - puts("DRAM: "); - print_size(size, " "); - printf("%s %s @ %sMHz", - clock_get_mem_manuf_name(mem_manuf), - clock_get_mem_type_name(mem_type), - strmhz(buf, frequency_mhz)); - putc('\n'); -} -#endif - -#ifdef CONFIG_ARCH_CPU_INIT -int arch_cpu_init(void) -{ - cpu_info_init(); - - return 0; -} -#endif diff --git a/src/cpu/samsung/s5p-common/gpio.h b/src/cpu/samsung/s5p-common/gpio.h deleted file mode 100644 index d098bc8..0000000 --- a/src/cpu/samsung/s5p-common/gpio.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * - * 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 S5P_GPIO_H_ -#define S5P_GPIO_H_ - -#include <cpu/samsung/s5p-common/cpu.h> /* FIXME: for S5PC110_GPIO_BASE */ - -#ifndef __ASSEMBLER__ -struct s5p_gpio_bank { - unsigned int con; - unsigned int dat; - unsigned int pull; - unsigned int drv; - unsigned int pdn_con; - unsigned int pdn_pull; - unsigned char res1[8]; -}; - -struct s5pc100_gpio { - struct s5p_gpio_bank a0; - struct s5p_gpio_bank a1; - struct s5p_gpio_bank b; - struct s5p_gpio_bank c; - struct s5p_gpio_bank d; - struct s5p_gpio_bank e0; - struct s5p_gpio_bank e1; - struct s5p_gpio_bank f0; - struct s5p_gpio_bank f1; - struct s5p_gpio_bank f2; - struct s5p_gpio_bank f3; - struct s5p_gpio_bank g0; - struct s5p_gpio_bank g1; - struct s5p_gpio_bank g2; - struct s5p_gpio_bank g3; - struct s5p_gpio_bank i; - struct s5p_gpio_bank j0; - struct s5p_gpio_bank j1; - struct s5p_gpio_bank j2; - struct s5p_gpio_bank j3; - struct s5p_gpio_bank j4; - struct s5p_gpio_bank k0; - struct s5p_gpio_bank k1; - struct s5p_gpio_bank k2; - struct s5p_gpio_bank k3; - struct s5p_gpio_bank l0; - struct s5p_gpio_bank l1; - struct s5p_gpio_bank l2; - struct s5p_gpio_bank l3; - struct s5p_gpio_bank l4; - struct s5p_gpio_bank h0; - struct s5p_gpio_bank h1; - struct s5p_gpio_bank h2; - struct s5p_gpio_bank h3; -}; - -struct s5pc110_gpio { - struct s5p_gpio_bank a0; - struct s5p_gpio_bank a1; - struct s5p_gpio_bank b; - struct s5p_gpio_bank c0; - struct s5p_gpio_bank c1; - struct s5p_gpio_bank d0; - struct s5p_gpio_bank d1; - struct s5p_gpio_bank e0; - struct s5p_gpio_bank e1; - struct s5p_gpio_bank f0; - struct s5p_gpio_bank f1; - struct s5p_gpio_bank f2; - struct s5p_gpio_bank f3; - struct s5p_gpio_bank g0; - struct s5p_gpio_bank g1; - struct s5p_gpio_bank g2; - struct s5p_gpio_bank g3; - struct s5p_gpio_bank i; - struct s5p_gpio_bank j0; - struct s5p_gpio_bank j1; - struct s5p_gpio_bank j2; - struct s5p_gpio_bank j3; - struct s5p_gpio_bank j4; - struct s5p_gpio_bank mp0_1; - struct s5p_gpio_bank mp0_2; - struct s5p_gpio_bank mp0_3; - struct s5p_gpio_bank mp0_4; - struct s5p_gpio_bank mp0_5; - struct s5p_gpio_bank mp0_6; - struct s5p_gpio_bank mp0_7; - struct s5p_gpio_bank mp1_0; - struct s5p_gpio_bank mp1_1; - struct s5p_gpio_bank mp1_2; - struct s5p_gpio_bank mp1_3; - struct s5p_gpio_bank mp1_4; - struct s5p_gpio_bank mp1_5; - struct s5p_gpio_bank mp1_6; - struct s5p_gpio_bank mp1_7; - struct s5p_gpio_bank mp1_8; - struct s5p_gpio_bank mp2_0; - struct s5p_gpio_bank mp2_1; - struct s5p_gpio_bank mp2_2; - struct s5p_gpio_bank mp2_3; - struct s5p_gpio_bank mp2_4; - struct s5p_gpio_bank mp2_5; - struct s5p_gpio_bank mp2_6; - struct s5p_gpio_bank mp2_7; - struct s5p_gpio_bank mp2_8; - struct s5p_gpio_bank res1[48]; - struct s5p_gpio_bank h0; - struct s5p_gpio_bank h1; - struct s5p_gpio_bank h2; - struct s5p_gpio_bank h3; -}; - -/* functions */ -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en); -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio); -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en); -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio); -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); - -/* GPIO pins per bank */ -#define GPIO_PER_BANK 8 - -static inline unsigned int s5p_gpio_base(int nr) -{ - return S5PC110_GPIO_BASE; -} - -#define s5pc110_gpio_get_nr(bank, pin) \ - ((((((unsigned int)&(((struct s5pc110_gpio *)S5PC110_GPIO_BASE)->bank))\ - - S5PC110_GPIO_BASE) / sizeof(struct s5p_gpio_bank)) \ - * GPIO_PER_BANK) + pin) -#endif - -/* Pin configurations */ -#define GPIO_INPUT 0x0 -#define GPIO_OUTPUT 0x1 -#define GPIO_IRQ 0xf -#define GPIO_FUNC(x) (x) - -/* Pull mode */ -#define GPIO_PULL_NONE 0x0 -#define GPIO_PULL_DOWN 0x1 -#define GPIO_PULL_UP 0x2 - -/* Drive Strength level */ -#define GPIO_DRV_1X 0x0 -#define GPIO_DRV_3X 0x1 -#define GPIO_DRV_2X 0x2 -#define GPIO_DRV_4X 0x3 -#define GPIO_DRV_FAST 0x0 -#define GPIO_DRV_SLOW 0x1 - -#endif /* S5P_GPIO_H_ */ diff --git a/src/cpu/samsung/s5p-common/power.h b/src/cpu/samsung/s5p-common/power.h deleted file mode 100644 index 57e2a2b..0000000 --- a/src/cpu/samsung/s5p-common/power.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2009 Samsung Electronics - * Kyungmin Park kyungmin.park@samsung.com - * Minkyu Kang mk7.kang@samsung.com - * - * 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_POWER_H_ -#define __ASM_ARM_ARCH_POWER_H_ - -/* - * Power control - */ -#define S5PC100_OTHERS 0xE0108200 -#define S5PC100_RST_STAT 0xE0108300 -#define S5PC100_SLEEP_WAKEUP (1 << 3) -#define S5PC100_WAKEUP_STAT 0xE0108304 -#define S5PC100_INFORM0 0xE0108400 - -#define S5PC110_RST_STAT 0xE010A000 -#define S5PC110_SLEEP_WAKEUP (1 << 3) -#define S5PC110_WAKEUP_STAT 0xE010C200 -#define S5PC110_OTHERS 0xE010E000 -#define S5PC110_USB_PHY_CON 0xE010E80C -#define S5PC110_INFORM0 0xE010F000 - -#endif diff --git a/src/cpu/samsung/s5p-common/pwm.c b/src/cpu/samsung/s5p-common/pwm.c deleted file mode 100644 index 5300420..0000000 --- a/src/cpu/samsung/s5p-common/pwm.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * - * Donghwa Lee dh09.lee@samsung.com - * - * 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 <common.h> -//#include <pwm.h> -#include <arch/io.h> -//#include <arch/pwm.h> -//#include <arch/clk.h> -/* FIXME(dhendrix): this is a godawful mess of similar-but-different includes... */ -#include <cpu/samsung/exynos5-common/clk.h> -#include <cpu/samsung/exynos5250/cpu.h> -#include <cpu/samsung/exynos5250/periph.h> -#include <cpu/samsung/s5p-common/pwm.h> -#include <cpu/samsung/s5p-common/clk.h> -//#include <arch/periph.h> - -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; -} - -int pwm_check_enabled(int pwm_id) -{ - const struct s5p_timer *pwm = - (struct s5p_timer *)samsung_get_base_timer(); - const unsigned long tcon = readl(&pwm->tcon); - - return tcon & TCON_START(pwm_id); -} - -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 = 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) -{ - 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 -1; -// return -ERANGE; - - if (duty_ns > period_ns) - return -1; -// 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 = 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/s5p-common/pwm.h b/src/cpu/samsung/s5p-common/pwm.h deleted file mode 100644 index 9d9370d..0000000 --- a/src/cpu/samsung/s5p-common/pwm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Kyungmin Park kyungmin.park@samsung.com - * Minkyu Kang mk7.kang@samsung.com - * - * 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 __S5P_COMMON_PWM_H_ -#define __S5P_COMMON_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 __ASSEMBLER__ -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 /* __ASSEMBLER__ */ - -/* FIXME(dhendrix): added missing prototypes... */ -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 /* __S5P_COMMON_PWM_H_ */ diff --git a/src/cpu/samsung/s5p-common/s3c24x0_i2c.c b/src/cpu/samsung/s5p-common/s3c24x0_i2c.c deleted file mode 100644 index 3e94ea7..0000000 --- a/src/cpu/samsung/s5p-common/s3c24x0_i2c.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * (C) Copyright 2002 - * David Mueller, ELSOFT AG, d.mueller@elsoft.ch - * - * 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 - */ - -/* This code should work for both the S3C2400 and the S3C2410 - * as they seem to have the same I2C controller inside. - * The different address mapping is handled by the s3c24xx.h files below. - */ - -#include <common.h> -#include <arch/io.h> -#include "clk.h" -#include "cpu/samsung/exynos5-common/clk.h" -#include "cpu/samsung/exynos5250/cpu.h" -#include "gpio.h" -#include "cpu/samsung/exynos5250/gpio.h" -#include "cpu/samsung/exynos5250/pinmux.h" - -//#include <fdtdec.h> -#include "device/i2c.h" -#include "s3c24x0_i2c.h" - -#define I2C_WRITE 0 -#define I2C_READ 1 - -#define I2C_OK 0 -#define I2C_NOK 1 -#define I2C_NACK 2 -#define I2C_NOK_LA 3 /* Lost arbitration */ -#define I2C_NOK_TOUT 4 /* time out */ - -#define I2CSTAT_BSY 0x20 /* Busy bit */ -#define I2CSTAT_NACK 0x01 /* Nack bit */ -#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ -#define I2CCON_IRPND 0x10 /* Interrupt pending bit */ -#define I2C_MODE_MT 0xC0 /* Master Transmit Mode */ -#define I2C_MODE_MR 0x80 /* Master Receive Mode */ -#define I2C_START_STOP 0x20 /* START / STOP */ -#define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */ - -/* The timeouts we live by */ -enum { - I2C_XFER_TIMEOUT_MS = 35, /* xfer to complete */ - I2C_INIT_TIMEOUT_MS = 1000, /* bus free on init */ - I2C_IDLE_TIMEOUT_MS = 100, /* waiting for bus idle */ - I2C_STOP_TIMEOUT_US = 200, /* waiting for stop events */ -}; - -/* We should not rely on any particular ordering of these IDs */ -#if 0 -#ifndef CONFIG_OF_CONTROL -static enum periph_id periph_for_dev[EXYNOS_I2C_MAX_CONTROLLERS] = { - PERIPH_ID_I2C0, - PERIPH_ID_I2C1, - PERIPH_ID_I2C2, - PERIPH_ID_I2C3, - PERIPH_ID_I2C4, - PERIPH_ID_I2C5, - PERIPH_ID_I2C6, - PERIPH_ID_I2C7, -}; -#endif -#endif - -static unsigned int g_current_bus __attribute__((section(".data"))); -static struct s3c24x0_i2c *g_early_i2c_config __attribute__((section(".data"))); - -static struct s3c24x0_i2c_bus i2c_bus[EXYNOS_I2C_MAX_CONTROLLERS] - __attribute__((section(".data"))); -static int i2c_busses __attribute__((section(".data"))); - -void i2c_set_early_reg(unsigned int base) -{ - g_early_i2c_config = (struct s3c24x0_i2c *)base; -} - -static struct s3c24x0_i2c_bus *get_bus(int bus_idx) -{ - /* If an early i2c config exists we just use that */ - if (g_early_i2c_config) { - /* FIXME: value not retained from i2c_set_early_reg()? (but then, how - * did if (!i2c) check pass earlier on? Corrupt value? */ - i2c_bus[0].regs = g_early_i2c_config; - return &i2c_bus[0]; - } - - if (bus_idx < i2c_busses) - return &i2c_bus[bus_idx]; - debug("Undefined bus: %d\n", bus_idx); - return NULL; -} - -static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void) -{ - return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE); -} - -static int WaitForXfer(struct s3c24x0_i2c *i2c) -{ - int i; - - i = I2C_XFER_TIMEOUT_MS * 20; - while (!(readl(&i2c->iiccon) & I2CCON_IRPND)) { - if (i == 0) { - debug("%s: i2c xfer timeout\n", __func__); - return I2C_NOK_TOUT; - } - udelay(50); - i--; - } - - return I2C_OK; -} - -static int IsACK(struct s3c24x0_i2c *i2c) -{ - return !(readl(&i2c->iicstat) & I2CSTAT_NACK); -} - -static void ReadWriteByte(struct s3c24x0_i2c *i2c) -{ - uint32_t x; - - x = readl(&i2c->iiccon); - writel(x & ~I2CCON_IRPND, &i2c->iiccon); - /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ -// writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon); -} - -static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) -{ - ulong freq, pres = 16, div; - - freq = clock_get_periph_rate(PERIPH_ID_I2C0); - /* calculate prescaler and divisor values */ - if ((freq / pres / (16 + 1)) > speed) - /* set prescaler to 512 */ - pres = 512; - - div = 0; - - while ((freq / pres / (div + 1)) > speed) - div++; - - /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */ - writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon); - - /* init to SLAVE REVEIVE and set slaveaddr */ - writel(0, &i2c->iicstat); - writel(slaveadd, &i2c->iicadd); - /* program Master Transmit (and implicit STOP) */ - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); -} - -/* TODO: determine if this is necessary to init board using FDT-provided info */ -#if 0 -void board_i2c_init(const void *blob) -{ - /* - * Turn off the early i2c configuration and init the i2c properly, - * this is done here to enable the use of i2c configs from FDT. - */ - i2c_set_early_reg(0); - -#ifdef CONFIG_OF_CONTROL - int node_list[EXYNOS_I2C_MAX_CONTROLLERS]; - int i, count; - - count = fdtdec_find_aliases_for_id(blob, "i2c", - COMPAT_SAMSUNG_S3C2440_I2C, node_list, - EXYNOS_I2C_MAX_CONTROLLERS); - - for (i = 0; i < count; i++) { - struct s3c24x0_i2c_bus *bus; - int node = node_list[i]; - - if (node < 0) - continue; - bus = &i2c_bus[i2c_busses]; - bus->regs = (struct s3c24x0_i2c *) - fdtdec_get_addr(blob, node, "reg"); - bus->id = (enum periph_id) - fdtdec_get_int(blob, node, "samsung,periph-id", -1); - bus->node = node; - bus->bus_num = i2c_busses++; - } -#else - int i; - - for (i = 0; i < EXYNOS_I2C_MAX_CONTROLLERS; i++) { - uintptr_t reg_addr = samsung_get_base_i2c() + - EXYNOS_I2C_SPACING * i; - - i2c_bus[i].regs = (struct s3c24x0_i2c_bus *)reg_addr; - i2c_bus[i].id = periph_for_dev[i]; - } - i2c_busses = EXYNOS_I2C_MAX_CONTROLLERS; -#endif -} -#endif - -/* - * MULTI BUS I2C support - */ -static void i2c_bus_init(struct s3c24x0_i2c_bus *i2c, unsigned int bus) -{ - exynos_pinmux_config(i2c->id, 0); - i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -} - -#ifdef CONFIG_I2C_MULTI_BUS -int i2c_set_bus_num(unsigned int bus) -{ - struct s3c24x0_i2c_bus *i2c; - - i2c = get_bus(bus); - if (!i2c) - return -1; - g_current_bus = bus; - i2c_bus_init(i2c, g_current_bus); - - return 0; -} - -unsigned int i2c_get_bus_num(void) -{ - return g_current_bus; -} -#endif - -#ifdef CONFIG_OF_CONTROL -int i2c_get_bus_num_fdt(const void *blob, int node) -{ - enum fdt_compat_id compat; - fdt_addr_t reg; - int i; - - compat = fdtdec_lookup(blob, node); - if (compat != COMPAT_SAMSUNG_S3C2440_I2C) { - debug("%s: Not a supported I2C node\n", __func__); - return -1; - } - - reg = fdtdec_get_addr(blob, node, "reg"); - for (i = 0; i < i2c_busses; i++) - if (reg == (fdt_addr_t)(uintptr_t)i2c_bus[i].regs) - return i; - - debug("%s: Can't find any matched I2C bus\n", __func__); - return -1; -} - -int i2c_reset_port_fdt(const void *blob, int node) -{ - struct s3c24x0_i2c_bus *i2c; - - int bus; - - bus = i2c_get_bus_num_fdt(blob, node); - if (bus < 0) { - printf("could not get bus for node %d\n", node); - return -1; - } - i2c = get_bus(bus); - if (!i2c) { - printf("get_bus() failed for node node %d\n", node); - return -1; - } - - i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - - return 0; -} -#endif - -/* - * Verify the whether I2C ACK was received or not - * - * @param i2c pointer to I2C register base - * @param buf array of data - * @param len length of data - * return I2C_OK when transmission done - * I2C_NACK otherwise - */ -static int i2c_send_verify(struct s3c24x0_i2c *i2c, unsigned char buf[], - unsigned char len) -{ - int i, result = I2C_OK; - - if (IsACK(i2c)) { - for (i = 0; (i < len) && (result == I2C_OK); i++) { - writel(buf[i], &i2c->iicds); - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - if (result == I2C_OK && !IsACK(i2c)) - result = I2C_NACK; - } - } else { - result = I2C_NACK; - } - - return result; -} - -void i2c_init(int speed, int slaveadd) -{ - struct s3c24x0_i2c_bus *i2c; - struct exynos5_gpio_part1 *gpio; - int i; - uint32_t x; - - /* By default i2c channel 0 is the current bus */ - g_current_bus = 0; - - i2c = get_bus(g_current_bus); - if (!i2c) - return; - - i2c_bus_init(i2c, g_current_bus); - - /* wait for some time to give previous transfer a chance to finish */ - i = I2C_INIT_TIMEOUT_MS * 20; - while ((readl(&i2c->regs->iicstat) & I2CSTAT_BSY) && (i > 0)) { - udelay(50); - i--; - } - - gpio = exynos_get_base_gpio1(); - /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ -// writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con); - x = readl(&gpio->b3.con); - writel((x & ~0x00FF) | 0x0022, &gpio->b3.con); - - i2c_ch_init(i2c->regs, speed, slaveadd); -} - -/* - * Send a STOP event and wait for it to have completed - * - * @param mode If it is a master transmitter or receiver - * @return I2C_OK if the line became idle before timeout I2C_NOK_TOUT otherwise - */ -static int i2c_send_stop(struct s3c24x0_i2c *i2c, int mode) -{ - int timeout; - - /* Setting the STOP event to fire */ - writel(mode | I2C_TXRX_ENA, &i2c->iicstat); - ReadWriteByte(i2c); - - /* Wait for the STOP to send and the bus to go idle */ - for (timeout = I2C_STOP_TIMEOUT_US; timeout > 0; timeout -= 5) { - if (!(readl(&i2c->iicstat) & I2CSTAT_BSY)) - return I2C_OK; - udelay(5); - } - - return I2C_NOK_TOUT; -} - -/* - * cmd_type is 0 for write, 1 for read. - * - * addr_len can take any value from 0-255, it is only limited - * by the char, we could make it larger if needed. If it is - * 0 we skip the address write cycle. - */ -static int i2c_transfer(struct s3c24x0_i2c *i2c, - unsigned char cmd_type, - unsigned char chip, - unsigned char addr[], - unsigned char addr_len, - unsigned char data[], - unsigned short data_len) -{ - int i, result, stop_bit_result; - uint32_t x; - - if (data == 0 || data_len == 0) { - /* Don't support data transfer of no length or to address 0 */ - debug("i2c_transfer: bad call\n"); - return I2C_NOK; - } - - /* Check I2C bus idle */ - i = I2C_IDLE_TIMEOUT_MS * 20; - while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) { - udelay(50); - i--; - } - - if (readl(&i2c->iicstat) & I2CSTAT_BSY) { - debug("%s: bus busy\n", __func__); - return I2C_NOK_TOUT; - } - - /* FIXME(dhendrix): cannot use nested macro (compilation failure) */ - //writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); - x = readl(&i2c->iiccon); - writel(x | I2CCON_ACKGEN, &i2c->iiccon); - - if (addr && addr_len) { - writel(chip, &i2c->iicds); - /* send START */ - writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, - &i2c->iicstat); - if (WaitForXfer(i2c) == I2C_OK) - result = i2c_send_verify(i2c, addr, addr_len); - else - result = I2C_NACK; - } else - result = I2C_NACK; - - switch (cmd_type) { - case I2C_WRITE: - if (result == I2C_OK) - result = i2c_send_verify(i2c, data, data_len); - else { - writel(chip, &i2c->iicds); - /* send START */ - writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, - &i2c->iicstat); - if (WaitForXfer(i2c) == I2C_OK) - result = i2c_send_verify(i2c, data, data_len); - } - - if (result == I2C_OK) - result = WaitForXfer(i2c); - - stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MT); - break; - - case I2C_READ: - { - int was_ok = (result == I2C_OK); - - writel(chip, &i2c->iicds); - /* resend START */ - writel(I2C_MODE_MR | I2C_TXRX_ENA | - I2C_START_STOP, &i2c->iicstat); - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - - if (was_ok || IsACK(i2c)) { - i = 0; - while ((i < data_len) && (result == I2C_OK)) { - /* disable ACK for final READ */ - if (i == data_len - 1) { - /* FIXME(dhendrix): nested macro */ -#if 0 - writel(readl(&i2c->iiccon) & - ~I2CCON_ACKGEN, - &i2c->iiccon); -#endif - x = readl(&i2c->iiccon) & ~I2CCON_ACKGEN; - writel(x, &i2c->iiccon); - } - ReadWriteByte(i2c); - result = WaitForXfer(i2c); - data[i] = readl(&i2c->iicds); - i++; - } - } else { - result = I2C_NACK; - } - - stop_bit_result = i2c_send_stop(i2c, I2C_MODE_MR); - break; - } - - default: - debug("i2c_transfer: bad call\n"); - result = stop_bit_result = I2C_NOK; - break; - } - - /* - * If the transmission went fine, then only the stop bit was left to - * fail. Otherwise, the real failure we're interested in came before - * that, during the actual transmission. - */ - return (result == I2C_OK) ? stop_bit_result : result; -} - -int i2c_probe(uchar chip) -{ - struct s3c24x0_i2c_bus *i2c; - uchar buf[1]; - int ret; - - i2c = get_bus(g_current_bus); - if (!i2c) - return -1; - buf[0] = 0; - - /* - * What is needed is to send the chip address and verify that the - * address was <ACK>ed (i.e. there was a chip at that address which - * drove the data line low). - */ - ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, 0, 0, buf, 1); - - return ret != I2C_OK; -} - -int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) -{ - struct s3c24x0_i2c_bus *i2c; - uchar xaddr[4]; - int ret; - - if (alen > 4) { - debug("I2C read: addr len %d not supported\n", alen); - return 1; - } - - if (alen > 0) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } - -#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW - /* - * EEPROM chips that implement "address overflow" are ones - * like Catalyst 24WC04/08/16 which has 9/10/11 bits of - * address and the extra bits end up in the "chip address" - * bit slots. This makes a 24WC08 (1Kbyte) chip look like - * four 256 byte chips. - * - * Note that we consider the length of the address field to - * still be one byte because the extra address bits are - * hidden in the chip address. - */ - if (alen > 0) - chip |= ((addr >> (alen * 8)) & - CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); -#endif - i2c = get_bus(g_current_bus); - if (!i2c) - return -1; - ret = i2c_transfer(i2c->regs, I2C_READ, chip << 1, &xaddr[4 - alen], - alen, buffer, len); - if (ret) { - debug("I2c read: failed %d\n", ret); - return 1; - } - return 0; -} - -int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) -{ - struct s3c24x0_i2c_bus *i2c; - uchar xaddr[4]; - int ret; - - if (alen > 4) { - debug("I2C write: addr len %d not supported\n", alen); - return 1; - } - - if (alen > 0) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } -#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW - /* - * EEPROM chips that implement "address overflow" are ones - * like Catalyst 24WC04/08/16 which has 9/10/11 bits of - * address and the extra bits end up in the "chip address" - * bit slots. This makes a 24WC08 (1Kbyte) chip look like - * four 256 byte chips. - * - * Note that we consider the length of the address field to - * still be one byte because the extra address bits are - * hidden in the chip address. - */ - if (alen > 0) - chip |= ((addr >> (alen * 8)) & - CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); -#endif - i2c = get_bus(g_current_bus); - if (!i2c) - return -1; - - ret = i2c_transfer(i2c->regs, I2C_WRITE, chip << 1, &xaddr[4 - alen], - alen, buffer, len); - - return ret != 0; -} diff --git a/src/cpu/samsung/s5p-common/s3c24x0_i2c.h b/src/cpu/samsung/s5p-common/s3c24x0_i2c.h deleted file mode 100644 index eb68af7..0000000 --- a/src/cpu/samsung/s5p-common/s3c24x0_i2c.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * 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 - */ - -#ifndef _S3C24X0_I2C_H -#define _S3C24X0_I2C_H - -/* FIXME: gross hack */ -#include "cpu/samsung/exynos5250/periph.h" - -struct s3c24x0_i2c { - u32 iiccon; - u32 iicstat; - u32 iicadd; - u32 iicds; - u32 iiclc; -}; - -struct s3c24x0_i2c_bus { - int node; /* device tree node */ - int bus_num; /* i2c bus number */ - struct s3c24x0_i2c *regs; - enum periph_id id; -}; -#endif /* _S3C24X0_I2C_H */ diff --git a/src/cpu/samsung/s5p-common/s5p_gpio.c b/src/cpu/samsung/s5p-common/s5p_gpio.c deleted file mode 100644 index 8daae59..0000000 --- a/src/cpu/samsung/s5p-common/s5p_gpio.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * - * 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 - */ - -/* FIXME(dhendrix): fix this up so it doesn't require a bunch of #ifdefs... */ -#include <common.h> -#include <gpio.h> -//#include <arch/io.h> -#include <gpio.h> -#include <arch/gpio.h> -#include <console/console.h> -#include <cpu/samsung/s5p-common/gpio.h> -#include <cpu/samsung/exynos5-common/gpio.h> -#include <cpu/samsung/exynos5250/gpio.h> /* FIXME: for gpio_decode_number prototype */ - -#define CON_MASK(x) (0xf << ((x) << 2)) -#define CON_SFR(x, v) ((v) << ((x) << 2)) - -#define DAT_MASK(x) (0x1 << (x)) -#define DAT_SET(x) (0x1 << (x)) - -#define PULL_MASK(x) (0x3 << ((x) << 1)) -#define PULL_MODE(x, v) ((v) << ((x) << 1)) - -#define DRV_MASK(x) (0x3 << ((x) << 1)) -#define DRV_SET(x, m) ((m) << ((x) << 1)) -#define RATE_MASK(x) (0x1 << (x + 16)) -#define RATE_SET(x) (0x1 << (x + 16)) - -struct gpio_info { - unsigned int reg_addr; /* Address of register for this part */ - unsigned int max_gpio; /* Maximum GPIO in this part */ -}; - -#ifdef CONFIG_CPU_SAMSUNG_EXYNOS5 - -#include <cpu/samsung/exynos5250/cpu.h> -static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = { - { EXYNOS5_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 }, - { EXYNOS5_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 }, - { EXYNOS5_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 }, - { EXYNOS5_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 }, - { EXYNOS5_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 }, - { EXYNOS5_GPIO_PART6_BASE, GPIO_MAX_PORT }, -}; - -#define HAVE_GENERIC_GPIO - -#elif defined(CONFIG_CPU_SAMSUNG_EXYNOS4) - -static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = { - { EXYNOS4_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 }, - { EXYNOS4_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 }, - { EXYNOS4_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 }, -}; - -#define HAVE_GENERIC_GPIO - -#endif - -/* This macro gets gpio pin offset from 0..7 */ -#define GPIO_BIT(x) ((x) & 0x7) - -//#ifdef HAVE_GENERIC_GPIO -static struct s5p_gpio_bank *gpio_get_bank(unsigned int gpio) -{ - const struct gpio_info *data; - unsigned int upto; - int i; - - for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS; - i++, upto = data->max_gpio, data++) { - if (gpio < data->max_gpio) { - struct s5p_gpio_bank *bank; - - bank = (struct s5p_gpio_bank *)data->reg_addr; - bank += (gpio - upto) / GPIO_PER_BANK; - return bank; - } - } - - assert(gpio < GPIO_MAX_PORT); /* ...which it will not be */ - return NULL; -} -//#endif - -/* TODO: Deprecation this interface in favour of asm-generic/gpio.h */ -void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg) -{ - unsigned int value; - - value = readl(&bank->con); - value &= ~CON_MASK(gpio); - value |= CON_SFR(gpio, cfg); - writel(value, &bank->con); -} - -void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en) -{ - unsigned int value; - - s5p_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_OUTPUT); - - value = readl(&bank->dat); - value &= ~DAT_MASK(gpio); - if (en) - value |= DAT_SET(gpio); - writel(value, &bank->dat); -} - -void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio) -{ - s5p_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_INPUT); -} - -void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en) -{ - unsigned int value; - - value = readl(&bank->dat); - value &= ~DAT_MASK(gpio); - if (en) - value |= DAT_SET(gpio); - writel(value, &bank->dat); -} - -unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio) -{ - unsigned int value; - - value = readl(&bank->dat); - return !!(value & DAT_MASK(gpio)); -} - -void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode) -{ - unsigned int value; - - value = readl(&bank->pull); - value &= ~PULL_MASK(gpio); - - switch (mode) { - case EXYNOS_GPIO_PULL_DOWN: - case EXYNOS_GPIO_PULL_UP: - value |= PULL_MODE(gpio, mode); - break; - default: - break; - } - - writel(value, &bank->pull); -} - -void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode) -{ - unsigned int value; - - value = readl(&bank->drv); - value &= ~DRV_MASK(gpio); - - switch (mode) { - case EXYNOS_GPIO_DRV_1X: - case EXYNOS_GPIO_DRV_2X: - case EXYNOS_GPIO_DRV_3X: - case EXYNOS_GPIO_DRV_4X: - value |= DRV_SET(gpio, mode); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode) -{ - unsigned int value; - - value = readl(&bank->drv); - value &= ~RATE_MASK(gpio); - - switch (mode) { - case EXYNOS_GPIO_DRV_FAST: - case EXYNOS_GPIO_DRV_SLOW: - value |= RATE_SET(gpio); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -/* Common GPIO API - only available on Exynos5 */ -/* FIXME(dhendrix): If this stuff is really only applicable to exynos5, - move it to a more sensible location. */ -#ifdef HAVE_GENERIC_GPIO - -void gpio_cfg_pin(int gpio, int cfg) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->con); - value &= ~CON_MASK(GPIO_BIT(gpio)); - value |= CON_SFR(GPIO_BIT(gpio), cfg); - writel(value, &bank->con); -} - -static int gpio_get_cfg(int gpio) -{ - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - int shift = GPIO_BIT(gpio) << 2; - - return (readl(&bank->con) & CON_MASK(GPIO_BIT(gpio))) >> shift; -} - -void gpio_set_pull(int gpio, int mode) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->pull); - value &= ~PULL_MASK(GPIO_BIT(gpio)); - - switch (mode) { - case EXYNOS_GPIO_PULL_DOWN: - case EXYNOS_GPIO_PULL_UP: - value |= PULL_MODE(GPIO_BIT(gpio), mode); - break; - default: - break; - } - - writel(value, &bank->pull); -} - -void gpio_set_drv(int gpio, int mode) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->drv); - value &= ~DRV_MASK(GPIO_BIT(gpio)); - - switch (mode) { - case EXYNOS_GPIO_DRV_1X: - case EXYNOS_GPIO_DRV_2X: - case EXYNOS_GPIO_DRV_3X: - case EXYNOS_GPIO_DRV_4X: - value |= DRV_SET(GPIO_BIT(gpio), mode); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -void gpio_set_rate(int gpio, int mode) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->drv); - value &= ~RATE_MASK(GPIO_BIT(gpio)); - - switch (mode) { - case EXYNOS_GPIO_DRV_FAST: - case EXYNOS_GPIO_DRV_SLOW: - value |= RATE_SET(GPIO_BIT(gpio)); - break; - default: - return; - } - - writel(value, &bank->drv); -} - -int gpio_request(unsigned gpio, const char *label) -{ - return 0; -} - -int gpio_free(unsigned gpio) -{ - return 0; -} - -int gpio_direction_input(unsigned gpio) -{ - gpio_cfg_pin(gpio, EXYNOS_GPIO_INPUT); - - return 0; -} - -int gpio_direction_output(unsigned gpio, int value) -{ - unsigned int val; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - gpio_cfg_pin(gpio, EXYNOS_GPIO_OUTPUT); - - val = readl(&bank->dat); - val &= ~DAT_MASK(GPIO_BIT(gpio)); - if (value) - val |= DAT_SET(GPIO_BIT(gpio)); - writel(val, &bank->dat); - - return 0; -} - -int gpio_get_value(unsigned gpio) -{ - unsigned int value; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - value = readl(&bank->dat); - return !!(value & DAT_MASK(GPIO_BIT(gpio))); -} - -int gpio_set_value(unsigned gpio, int value) -{ - unsigned int val; - struct s5p_gpio_bank *bank = gpio_get_bank(gpio); - - val = readl(&bank->dat); - val &= ~DAT_MASK(GPIO_BIT(gpio)); - if (value) - val |= DAT_SET(GPIO_BIT(gpio)); - writel(val, &bank->dat); - - return 0; -} -#else - -static int s5p_gpio_get_pin(unsigned gpio) -{ - return gpio % GPIO_PER_BANK; -} - -/* - * If we have the old-style GPIO numbering setup, use these functions - * which don't necessary provide sequentially increasing GPIO numbers. - */ -static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio) -{ - int bank = gpio / GPIO_PER_BANK; - bank *= sizeof(struct s5p_gpio_bank); - - return (struct s5p_gpio_bank *) (s5p_gpio_base(gpio) + bank); -} - -int gpio_request(unsigned gpio, const char *label) -{ - return 0; -} - -int gpio_free(unsigned gpio) -{ - return 0; -} - -int gpio_direction_input(unsigned gpio) -{ - s5p_gpio_direction_input(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio)); - return 0; -} - -int gpio_direction_output(unsigned gpio, int value) -{ - s5p_gpio_direction_output(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio), value); - return 0; -} - -int gpio_get_value(unsigned gpio) -{ - return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio)); -} - -int gpio_set_value(unsigned gpio, int value) -{ - s5p_gpio_set_value(s5p_gpio_get_bank(gpio), - s5p_gpio_get_pin(gpio), value); - - return 0; -} - -#endif /* HAVE_GENERIC_GPIO */ - -/* - * Add a delay here to give the lines time to settle - * TODO(sjg): 1us does not always work, 2 is stable, so use 5 to be safe - * Come back to this and sort out what the datasheet says - */ -#define GPIO_DELAY_US 5 - -#ifndef __BOOT_BLOCK__ -/* - * FIXME(dhendrix): These functions use udelay, which has dependencies on - * pwm code and timer code. These aren't necessary for the bootblock and - * bloat the image significantly. - */ -int gpio_read_mvl3(unsigned gpio) -{ - int high, low; - enum mvl3 value; - - if (gpio >= GPIO_MAX_PORT) - return -1; - - gpio_direction_input(gpio); - gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP); - udelay(GPIO_DELAY_US); - high = gpio_get_value(gpio); - gpio_set_pull(gpio, EXYNOS_GPIO_PULL_DOWN); - udelay(GPIO_DELAY_US); - low = gpio_get_value(gpio); - - if (high && low) /* external pullup */ - value = LOGIC_1; - else if (!high && !low) /* external pulldown */ - value = LOGIC_0; - else /* floating */ - value = LOGIC_Z; - - /* - * Check if line is externally pulled high and - * configure the internal pullup to match. For - * floating and pulldowns, the GPIO is already - * configured with an internal pulldown from the - * above test. - */ - if (value == LOGIC_1) - gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP); - - return value; -} - -int gpio_decode_number(unsigned gpio_list[], int count) -{ - int result = 0; - int multiplier = 1; - int gpio, i, value; - enum mvl3 mvl3; - - for (i = 0; i < count; i++) { - gpio = gpio_list[i]; - - mvl3 = gpio_read_mvl3(gpio); - if (mvl3 == LOGIC_1) - value = 2; - else if (mvl3 == LOGIC_0) - value = 1; - else if (mvl3 == LOGIC_Z) - value = 0; - else - return -1; - - result += value * multiplier; - multiplier *= 3; - } - - return result; -} -#endif /* __BOOT_BLOCK__ */ - -static const char *get_cfg_name(int cfg) -{ - static char name[8]; - - if (cfg == EXYNOS_GPIO_INPUT) - return "input"; - else if (cfg == EXYNOS_GPIO_OUTPUT) - return "output"; - printk(BIOS_INFO, "func %d", cfg); -// sprintf(name, "func %d", cfg); - - return name; -} - -/* - * Display Exynos GPIO information - */ -void gpio_info(void) -{ - unsigned gpio; - - for (gpio = 0; gpio < GPIO_MAX_PORT; gpio++) { - int cfg = gpio_get_cfg(gpio); - - printk(BIOS_INFO, "GPIO_%-3d: %s", gpio, get_cfg_name(cfg)); - if (cfg == EXYNOS_GPIO_INPUT || cfg == EXYNOS_GPIO_OUTPUT) - printk(BIOS_INFO, ", value = %d", gpio_get_value(gpio)); - printk(BIOS_INFO, "\n"); - } -} diff --git a/src/cpu/samsung/s5p-common/sromc.c b/src/cpu/samsung/s5p-common/sromc.c deleted file mode 100644 index 091e8d1..0000000 --- a/src/cpu/samsung/s5p-common/sromc.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 Samsung Electronics - * Naveen Krishna Ch ch.naveen@samsung.com - * - * 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 <common.h> -#include <asm/io.h> -#include <asm/arch/sromc.h> - -/* - * s5p_config_sromc() - select the proper SROMC Bank and configure the - * band width control and bank control registers - * srom_bank - SROM - * srom_bw_conf - SMC Band witdh reg configuration value - * srom_bc_conf - SMC Bank Control reg configuration value - */ -void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf) -{ - u32 tmp; - struct s5p_sromc *srom = - (struct s5p_sromc *)samsung_get_base_sromc(); - - /* Configure SMC_BW register to handle proper SROMC bank */ - tmp = srom->bw; - tmp &= ~(0xF << (srom_bank * 4)); - tmp |= srom_bw_conf; - srom->bw = tmp; - - /* Configure SMC_BC register */ - srom->bc[srom_bank] = srom_bc_conf; -} diff --git a/src/cpu/samsung/s5p-common/sromc.h b/src/cpu/samsung/s5p-common/sromc.h deleted file mode 100644 index fe73b37..0000000 --- a/src/cpu/samsung/s5p-common/sromc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * (C) Copyright 2010 Samsung Electronics - * Naveen Krishna Ch ch.naveen@samsung.com - * - * 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 - * - * Note: This file contains the register description for Memory subsystem - * (SROM, NAND Flash, OneNand, DDR, OneDRAM) on S5PC1XX. - * - * Only SROMC is defined as of now - */ - -#ifndef __ASM_ARCH_SROMC_H_ -#define __ASM_ARCH_SROMC_H_ - -#define SMC_DATA16_WIDTH(x) (1<<((x*4)+0)) -#define SMC_BYTE_ADDR_MODE(x) (1<<((x*4)+1)) /* 0-> Half-word base address*/ - /* 1-> Byte base address*/ -#define SMC_WAIT_ENABLE(x) (1<<((x*4)+2)) -#define SMC_BYTE_ENABLE(x) (1<<((x*4)+3)) - -#define SMC_BC_TACS(x) (x << 28) /* 0clk address set-up */ -#define SMC_BC_TCOS(x) (x << 24) /* 4clk chip selection set-up */ -#define SMC_BC_TACC(x) (x << 16) /* 14clk access cycle */ -#define SMC_BC_TCOH(x) (x << 12) /* 1clk chip selection hold */ -#define SMC_BC_TAH(x) (x << 8) /* 4clk address holding time */ -#define SMC_BC_TACP(x) (x << 4) /* 6clk page mode access cycle */ -#define SMC_BC_PMC(x) (x << 0) /* normal(1data)page mode configuration */ - -#ifndef __ASSEMBLER__ -struct s5p_sromc { - unsigned int bw; - unsigned int bc[6]; -}; -#endif /* __ASSEMBLER__ */ - -/* Configure the Band Width and Bank Control Regs for required SROMC Bank */ -void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf); - -#endif /* __ASM_ARCH_SMC_H_ */ diff --git a/src/cpu/samsung/s5p-common/timer.c b/src/cpu/samsung/s5p-common/timer.c deleted file mode 100644 index c6ed830..0000000 --- a/src/cpu/samsung/s5p-common/timer.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2009 Samsung Electronics - * Heungjun Kim riverful.kim@samsung.com - * Inki Dae inki.dae@samsung.com - * Minkyu Kang mk7.kang@samsung.com - * - * 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 <common.h> -#include <arch/io.h> -//#include <cpu/samsung/exynos5250/pwm.h> -//#include <cpu/samsung/exynos5250/clk.h> -#include <cpu/samsung/s5p-common/pwm.h> -#include <cpu/samsung/s5p-common/clk.h> -#include <cpu/samsung/exynos5250/cpu.h> -#include <cpu/samsung/exynos5-common/exynos5-common.h> - -//#include <pwm.h> - -//DECLARE_GLOBAL_DATA_PTR; -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 (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 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 */ - //gd->timer_reset_value = 0; - timer_reset_value = 0; - - /* Use this as the last timer value we saw */ - //gd->lastinc = timer_get_us_down(); - lastinc = timer_get_us_down(); - } - - return 0; -} - -/* - * timer without interrupts - */ -unsigned long get_timer(unsigned long base) -{ - 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. - */ -#if 0 - gd->timer_reset_value += gd->lastinc - now; - gd->lastinc = now; - - /* Divide by 1000 to convert from us to ms */ - return gd->timer_reset_value / 1000 - base; -#endif - timer_reset_value += lastinc - now; - lastinc = now; - - /* Divide by 1000 to convert from us to ms */ - return timer_reset_value / 1000 - base; -} - -unsigned long timer_get_us(void) -{ - struct s5p_timer *const timer = s5p_get_base_timer(); - unsigned long now_downward_us = readl(&timer->tcnto4); - - /* - * Note that this timer counts downward. The pre-SPL process (BL1) - * takes about 100ms, so add this in here. - */ - return CONFIG_SPL_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) - ; -} - -/* - * 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; -} - -unsigned long timer_get_boot_us(void) -{ - return timer_get_us(); -} diff --git a/src/cpu/samsung/s5p-common/uart.h b/src/cpu/samsung/s5p-common/uart.h deleted file mode 100644 index bf396cc..0000000 --- a/src/cpu/samsung/s5p-common/uart.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * (C) Copyright 2009 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * Heungjun Kim riverful.kim@samsung.com - * - * 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_ARCH_UART_H_ -#define __ASM_ARCH_UART_H_ - -#ifndef __ASSEMBLER__ -/* baudrate rest value */ -union br_rest { - unsigned short slot; /* udivslot */ - unsigned char value; /* ufracval */ -}; - -struct s5p_uart { - unsigned int ulcon; - unsigned int ucon; - unsigned int ufcon; - unsigned int umcon; - unsigned int utrstat; - unsigned int uerstat; - unsigned int ufstat; - unsigned int umstat; - unsigned char utxh; - unsigned char res1[3]; - unsigned char urxh; - unsigned char res2[3]; - unsigned int ubrdiv; - union br_rest rest; - unsigned char res3[0x3d0]; -}; - -static inline int s5p_uart_divslot(void) -{ - return 1; -} - -#endif /* __ASSEMBLER__ */ - -#endif diff --git a/src/cpu/samsung/s5p-common/watchdog.h b/src/cpu/samsung/s5p-common/watchdog.h deleted file mode 100644 index 5b3b651..0000000 --- a/src/cpu/samsung/s5p-common/watchdog.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * Heungjun Kim riverful.kim@samsung.com - * - * 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 - */ - -#ifndef __ASM_ARM_ARCH_COMMON_WATCHDOG_H_ -#define __ASM_ARM_ARCH_COMMON_WATCHDOG_H_ - -#define WTCON_RESET_OFFSET 0 -#define WTCON_INTEN_OFFSET 2 -#define WTCON_CLKSEL_OFFSET 3 -#define WTCON_EN_OFFSET 5 -#define WTCON_PRE_OFFSET 8 - -#define WTCON_CLK_16 0x0 -#define WTCON_CLK_32 0x1 -#define WTCON_CLK_64 0x2 -#define WTCON_CLK_128 0x3 - -#define WTCON_CLK(x) ((x & 0x3) << WTCON_CLKSEL_OFFSET) -#define WTCON_PRESCALER(x) ((x) << WTCON_PRE_OFFSET) -#define WTCON_EN (0x1 << WTCON_EN_OFFSET) -#define WTCON_RESET (0x1 << WTCON_RESET_OFFSET) -#define WTCON_INT (0x1 << WTCON_INTEN_OFFSET) - -#ifndef __ASSEMBLER__ -struct s5p_watchdog { - unsigned int wtcon; - unsigned int wtdat; - unsigned int wtcnt; - unsigned int wtclrint; -}; - -/* functions */ -void wdt_stop(void); -void wdt_start(unsigned int timeout); -#endif /* __ASSEMBLER__ */ - -#endif diff --git a/src/cpu/samsung/s5p-common/wdt.c b/src/cpu/samsung/s5p-common/wdt.c deleted file mode 100644 index 94acc1e..0000000 --- a/src/cpu/samsung/s5p-common/wdt.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * Minkyu Kang mk7.kang@samsung.com - * - * 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 <common.h> -#include <asm/io.h> -#include <asm/arch/watchdog.h> - -#define PRESCALER_VAL 255 - -void wdt_stop(void) -{ - struct s5p_watchdog *wdt = - (struct s5p_watchdog *)samsung_get_base_watchdog(); - unsigned int wtcon; - - wtcon = readl(&wdt->wtcon); - wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET); - - writel(wtcon, &wdt->wtcon); -} - -void wdt_start(unsigned int timeout) -{ - struct s5p_watchdog *wdt = - (struct s5p_watchdog *)samsung_get_base_watchdog(); - unsigned int wtcon; - - wdt_stop(); - - wtcon = readl(&wdt->wtcon); - wtcon |= (WTCON_EN | WTCON_CLK(WTCON_CLK_128)); - wtcon &= ~WTCON_INT; - wtcon |= WTCON_RESET; - wtcon |= WTCON_PRESCALER(PRESCALER_VAL); - - writel(timeout, &wdt->wtdat); - writel(timeout, &wdt->wtcnt); - writel(wtcon, &wdt->wtcon); -}