aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7
diff options
context:
space:
mode:
authorJeong-Hyeon Kim <jhkim@insignal.co.kr>2012-08-29 12:28:26 +0900
committerJohn Rigby <john.rigby@linaro.org>2012-12-06 13:51:42 -0700
commit4a703be87762dfd8753ad77af235f2db252592e3 (patch)
treef5eae01e95873ac50c9c41b03738b137a0dec5e8 /arch/arm/cpu/armv7
parentcd191553c40ab35703847ea2bb1f4c360fc3a49e (diff)
EXYNOS: additional Exynos4 SoC series support
- 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>
Diffstat (limited to 'arch/arm/cpu/armv7')
-rw-r--r--arch/arm/cpu/armv7/exynos/clock.c67
-rw-r--r--arch/arm/cpu/armv7/exynos/pinmux.c241
2 files changed, 308 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 680aeeb4d..002a49390 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -92,6 +92,70 @@ static unsigned long exynos4_get_pll_clk(int pllreg)
return fout;
}
+/* exynos4: return pll clock frequency */
+static unsigned long exynos4412_get_pll_clk(int pllreg)
+{
+ struct exynos4412_clock *clk =
+ (struct exynos4412_clock *)samsung_get_base_clock();
+ unsigned long r, m, p, s, k = 0, mask, fout;
+ unsigned int freq;
+
+ switch (pllreg) {
+ case APLL:
+ r = readl(&clk->apll_con0);
+ break;
+ case MPLL:
+ r = readl(&clk->mpll_con0);
+ break;
+ case EPLL:
+ r = readl(&clk->epll_con0);
+ k = readl(&clk->epll_con1);
+ break;
+ case VPLL:
+ r = readl(&clk->vpll_con0);
+ k = readl(&clk->vpll_con1);
+ break;
+ default:
+ printf("Unsupported PLL (%d)\n", pllreg);
+ return 0;
+ }
+
+ /*
+ * APLL_CON: MIDV [25:16]
+ * MPLL_CON: MIDV [25:16]
+ * EPLL_CON: MIDV [24:16]
+ * VPLL_CON: MIDV [24:16]
+ */
+ if (pllreg == APLL || pllreg == MPLL)
+ mask = 0x3ff;
+ else
+ mask = 0x1ff;
+
+ m = (r >> 16) & mask;
+
+ /* PDIV [13:8] */
+ p = (r >> 8) & 0x3f;
+ /* SDIV [2:0] */
+ s = r & 0x7;
+
+ freq = CONFIG_SYS_CLK_FREQ;
+
+ if (pllreg == EPLL) {
+ k = k & 0xffff;
+ /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
+ fout = (m + k / 65536) * (freq / (p * (1 << s)));
+ } else if (pllreg == VPLL) {
+ k = k & 0xffff;
+ /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
+ fout = (m + k / 65536) * (freq / (p * (1 << s)));
+ } else {
+ /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
+ fout = m * (freq / (p * (1 << s)));
+ }
+
+ return fout;
+}
+
/* exynos5: return pll clock frequency */
static unsigned long exynos5_get_pll_clk(int pllreg)
{
@@ -745,6 +809,9 @@ unsigned long get_pll_clk(int pllreg)
if (cpu_is_exynos5())
return exynos5_get_pll_clk(pllreg);
else
+ if (cpu_is_exynos4412())
+ return exynos4412_get_pll_clk(pllreg);
+ else
return exynos4_get_pll_clk(pllreg);
}
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
index 7776add9d..0746878a2 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;