
From: Jeong-Hyeon Kim jhkim@insignal.co.kr
- Fixed MPLL register address It's different between Exynos4210 and Exynos4412.
- Added pinmux functions for Exynos4
- Added extended gpios for Exynos4412 Exynos4412 has more gpios than Exynos4210.
Signed-off-by: Jeong-Hyeon Kim jhkim@insignal.co.kr --- arch/arm/cpu/armv7/exynos/clock.c | 11 ++ arch/arm/cpu/armv7/exynos/pinmux.c | 241 ++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/clock.h | 27 ++++ arch/arm/include/asm/arch-exynos/cpu.h | 4 + arch/arm/include/asm/arch-exynos/gpio.h | 21 +++- 5 files changed, 303 insertions(+), 1 deletions(-)
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 680aeeb..84a6725 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -79,14 +79,25 @@ static unsigned long exynos4_get_pll_clk(int pllreg) /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */ fout = (m + k / 65536) * (freq / (p * (1 << s))); } else if (pllreg == VPLL) { +#ifdef CONFIG_EXYNOS4210 k = k & 0xfff; /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */ fout = (m + k / 1024) * (freq / (p * (1 << s))); +#else + k = k & 0xffff; + /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */ + fout = (m + k / 65536) * (freq / (p * (1 << s))); +#endif } else { +#ifdef CONFIG_EXYNOS4210 if (s < 1) s = 1; /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */ fout = m * (freq / (p * (1 << (s - 1)))); +#else + /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ + fout = m * (freq / (p * (1 << s))); +#endif }
return fout; diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index 7776add..0746878 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -26,6 +26,245 @@ #include <asm/arch/pinmux.h> #include <asm/arch/sromc.h>
+static void exynos4_uart_config(int peripheral) +{ + struct exynos4_gpio_part1 *gpio1 = + (struct exynos4_gpio_part1 *) samsung_get_base_gpio_part1(); + struct s5p_gpio_bank *bank; + int i, start, count; + + switch (peripheral) { + case PERIPH_ID_UART0: + bank = &gpio1->a0; + start = 0; + count = 4; + break; + case PERIPH_ID_UART1: + bank = &gpio1->a0; + start = 4; + count = 4; + break; + case PERIPH_ID_UART2: + bank = &gpio1->a1; + start = 0; + count = 4; + break; + case PERIPH_ID_UART3: + bank = &gpio1->a1; + start = 4; + count = 2; + break; + } + for (i = start; i < start + count; i++) { + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + } +} + +static int exynos4_mmc_config(int peripheral, int flags) +{ + struct exynos4_gpio_part2 *gpio2 = + (struct exynos4_gpio_part2 *) samsung_get_base_gpio_part2(); + struct s5p_gpio_bank *bank, *bank_ext; + int i, start = 0, gpio_func = 0; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + bank = &gpio2->k0; + bank_ext = &gpio2->k1; + start = 3; + gpio_func = GPIO_FUNC(0x2); + break; + case PERIPH_ID_SDMMC1: + bank = &gpio2->k1; + bank_ext = NULL; + break; + case PERIPH_ID_SDMMC2: + bank = &gpio2->k2; + bank_ext = &gpio2->k3; + start = 3; + gpio_func = GPIO_FUNC(0x3); + break; + case PERIPH_ID_SDMMC3: + bank = &gpio2->k3; + bank_ext = NULL; + break; + } + if ((flags & PINMUX_FLAG_8BIT_MODE) && !bank_ext) { + debug("SDMMC device %d does not support 8bit mode", + peripheral); + return -1; + } + if (flags & PINMUX_FLAG_8BIT_MODE) { + for (i = start; i <= (start + 3); i++) { + s5p_gpio_cfg_pin(bank_ext, i, gpio_func); + s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X); + } + } + for (i = 0; i < 2; i++) { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_NONE); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + for (i = 3; i <= 6; i++) { + s5p_gpio_cfg_pin(bank, i, GPIO_FUNC(0x2)); + s5p_gpio_set_pull(bank, i, GPIO_PULL_UP); + s5p_gpio_set_drv(bank, i, GPIO_DRV_4X); + } + return 0; +} + +static void exynos4_sromc_config(int flags) +{ + struct exynos4_gpio_part2 *gpio2 = + (struct exynos4_gpio_part2 *) samsung_get_base_gpio_part2(); + int i; + + /* + * SROM:CS1 and EBI + * + * GPY0[0] SROM_CSn[0] + * GPY0[1] SROM_CSn[1](2) + * GPY0[2] SROM_CSn[2] + * GPY0[3] SROM_CSn[3] + * GPY0[4] EBI_OEn(2) + * GPY0[5] EBI_EEn(2) + * + * GPY1[0] EBI_BEn[0](2) + * GPY1[1] EBI_BEn[1](2) + * GPY1[2] SROM_WAIT(2) + * GPY1[3] EBI_DATA_RDn(2) + */ + s5p_gpio_cfg_pin(&gpio2->y0, (flags & PINMUX_FLAG_BANK), + GPIO_FUNC(2)); + s5p_gpio_cfg_pin(&gpio2->y0, 4, GPIO_FUNC(2)); + s5p_gpio_cfg_pin(&gpio2->y0, 5, GPIO_FUNC(2)); + + for (i = 0; i < 4; i++) + s5p_gpio_cfg_pin(&gpio2->y1, i, GPIO_FUNC(2)); + + /* + * EBI: 8 Addrss Lines + * + * GPY3[0] EBI_ADDR[0](2) + * GPY3[1] EBI_ADDR[1](2) + * GPY3[2] EBI_ADDR[2](2) + * GPY3[3] EBI_ADDR[3](2) + * GPY3[4] EBI_ADDR[4](2) + * GPY3[5] EBI_ADDR[5](2) + * GPY3[6] EBI_ADDR[6](2) + * GPY3[7] EBI_ADDR[7](2) + * + * EBI: 16 Data Lines + * + * GPY5[0] EBI_DATA[0](2) + * GPY5[1] EBI_DATA[1](2) + * GPY5[2] EBI_DATA[2](2) + * GPY5[3] EBI_DATA[3](2) + * GPY5[4] EBI_DATA[4](2) + * GPY5[5] EBI_DATA[5](2) + * GPY5[6] EBI_DATA[6](2) + * GPY5[7] EBI_DATA[7](2) + * + * GPY6[0] EBI_DATA[8](2) + * GPY6[1] EBI_DATA[9](2) + * GPY6[2] EBI_DATA[10](2) + * GPY6[3] EBI_DATA[11](2) + * GPY6[4] EBI_DATA[12](2) + * GPY6[5] EBI_DATA[13](2) + * GPY6[6] EBI_DATA[14](2) + * GPY6[7] EBI_DATA[15](2) + */ + for (i = 0; i < 8; i++) { + s5p_gpio_cfg_pin(&gpio2->y3, i, GPIO_FUNC(2)); + s5p_gpio_set_pull(&gpio2->y3, i, GPIO_PULL_UP); + + s5p_gpio_cfg_pin(&gpio2->y5, i, GPIO_FUNC(2)); + s5p_gpio_set_pull(&gpio2->y5, i, GPIO_PULL_UP); + + s5p_gpio_cfg_pin(&gpio2->y6, i, GPIO_FUNC(2)); + s5p_gpio_set_pull(&gpio2->y6, i, GPIO_PULL_UP); + } +} + +static void exynos4_i2c_config(int peripheral, int flags) +{ + + struct exynos4_gpio_part1 *gpio1 = + (struct exynos4_gpio_part1 *) samsung_get_base_gpio_part1(); + + switch (peripheral) { + case PERIPH_ID_I2C0: + s5p_gpio_cfg_pin(&gpio1->d1, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->d1, 1, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + s5p_gpio_cfg_pin(&gpio1->d1, 2, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->d1, 3, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + s5p_gpio_cfg_pin(&gpio1->b, 0, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b, 1, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C5: + s5p_gpio_cfg_pin(&gpio1->b, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + s5p_gpio_cfg_pin(&gpio1->c1, 3, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio1->c1, 4, GPIO_FUNC(0x4)); + break; + case PERIPH_ID_I2C7: + s5p_gpio_cfg_pin(&gpio1->d0, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->d0, 3, GPIO_FUNC(0x3)); + break; + } +} + +static int exynos4_pinmux_config(int peripheral, int flags) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + exynos4_uart_config(peripheral); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC1: + case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC3: + return exynos4_mmc_config(peripheral, flags); + case PERIPH_ID_SROMC: + exynos4_sromc_config(flags); + break; + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + exynos4_i2c_config(peripheral, flags); + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + static void exynos5_uart_config(int peripheral) { struct exynos5_gpio_part1 *gpio1 = @@ -269,6 +508,8 @@ int exynos_pinmux_config(int peripheral, int flags) { if (cpu_is_exynos5()) return exynos5_pinmux_config(peripheral, flags); + else if (cpu_is_exynos4()) + return exynos4_pinmux_config(peripheral, flags); else { debug("pinmux functionality not supported\n"); return -1; diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h index fce38ef..e238810 100644 --- a/arch/arm/include/asm/arch-exynos/clock.h +++ b/arch/arm/include/asm/arch-exynos/clock.h @@ -57,10 +57,20 @@ struct exynos4_clock { unsigned char res16[0xec]; unsigned int epll_con0; unsigned int epll_con1; +#ifdef CONFIG_EXYNOS4210 unsigned char res17[0x8]; +#else + unsigned int epll_con2; + unsigned char res17[0x4]; +#endif unsigned int vpll_con0; unsigned int vpll_con1; +#ifdef CONFIG_EXYNOS4210 unsigned char res18[0xe8]; +#else + unsigned int vpll_con2; + unsigned char res18[0xe4]; +#endif unsigned int src_top0; unsigned int src_top1; unsigned char res19[0x8]; @@ -161,7 +171,16 @@ struct exynos4_clock { unsigned char res38[0x8c]; unsigned int clkout_cmu_top; unsigned int clkout_cmu_top_div_stat; +#ifdef CONFIG_EXYNOS4210 unsigned char res39[0x37f8]; +#else + unsigned char res39[0x3600]; + unsigned int mpll_lock; + unsigned char res3a[0xfc]; + unsigned int mpll_con0; + unsigned int mpll_con1; + unsigned char res3b[0xf0]; +#endif unsigned int src_dmc; unsigned char res40[0xfc]; unsigned int src_mask_dmc; @@ -195,14 +214,22 @@ struct exynos4_clock { unsigned int maxperf; unsigned char res51[0x2f78]; unsigned int apll_lock; +#ifdef CONFIG_EXYNOS4210 unsigned char res52[0x4]; unsigned int mpll_lock; +#else + unsigned char res52[0x8]; +#endif unsigned char res53[0xf4]; unsigned int apll_con0; unsigned int apll_con1; +#ifdef CONFIG_EXYNOS4210 unsigned int mpll_con0; unsigned int mpll_con1; unsigned char res54[0xf0]; +#else + unsigned char res54[0xf8]; +#endif unsigned int src_cpu; unsigned char res55[0x1fc]; unsigned int mux_stat_cpu; diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 2cd4ae1..d1117c0 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -55,7 +55,11 @@ #define EXYNOS4_MODEM_BASE 0x13A00000 #define EXYNOS4_USBPHY_CONTROL 0x10020704
+#ifdef CONFIG_EXYNOS4412 +#define EXYNOS4_GPIO_PART4_BASE 0x106E0000 +#else #define EXYNOS4_GPIO_PART4_BASE DEVICE_NOT_AVAILABLE +#endif #define EXYNOS4_DP_BASE DEVICE_NOT_AVAILABLE
/* EXYNOS5 */ diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h index 97be4ea..9539aa0 100644 --- a/arch/arm/include/asm/arch-exynos/gpio.h +++ b/arch/arm/include/asm/arch-exynos/gpio.h @@ -49,6 +49,9 @@ struct exynos4_gpio_part1 { struct s5p_gpio_bank f1; struct s5p_gpio_bank f2; struct s5p_gpio_bank f3; + struct s5p_gpio_bank res1[2]; + struct s5p_gpio_bank j0; + struct s5p_gpio_bank j1; };
struct exynos4_gpio_part2 { @@ -68,7 +71,13 @@ struct exynos4_gpio_part2 { struct s5p_gpio_bank y4; struct s5p_gpio_bank y5; struct s5p_gpio_bank y6; - struct s5p_gpio_bank res1[80]; + struct s5p_gpio_bank res1[3]; + struct s5p_gpio_bank m0; + struct s5p_gpio_bank m1; + struct s5p_gpio_bank m2; + struct s5p_gpio_bank m3; + struct s5p_gpio_bank m4; + struct s5p_gpio_bank res2[72]; struct s5p_gpio_bank x0; struct s5p_gpio_bank x1; struct s5p_gpio_bank x2; @@ -79,6 +88,16 @@ struct exynos4_gpio_part3 { struct s5p_gpio_bank z; };
+struct exynos4_gpio_part4 { + struct s5p_gpio_bank v0; + struct s5p_gpio_bank v1; + struct s5p_gpio_bank res1[1]; + struct s5p_gpio_bank v2; + struct s5p_gpio_bank v3; + struct s5p_gpio_bank res2[1]; + struct s5p_gpio_bank v4; +}; + struct exynos5_gpio_part1 { struct s5p_gpio_bank a0; struct s5p_gpio_bank a1;