Patchwork [U-Boot,v2,2/4] ARM: EXYNOS: Add support for Exynos5 based SoCs

login
register
mail settings
Submitter Chander Kashyap
Date Jan. 9, 2012, 6:40 a.m.
Message ID <1326091215-2148-3-git-send-email-chander.kashyap@linaro.org>
Download mbox | patch
Permalink /patch/134964/
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Comments

Chander Kashyap - Jan. 9, 2012, 6:40 a.m.
Samsung's ARM Cortex-A15 based SoCs are known as Exynos5 series of
SoCs. This patch adds the support for Exynos5.

Signed-off-by: Chander Kashyap <chander.kashyap@linaro.org>
---
Changes for v2:
	- This patch was part of "EXYNOS: Add SMDK5250 board support"
	- Now it is seprated as SoC support.

 arch/arm/cpu/armv7/exynos/clock.c        |  209 +++++++++++++++++++-
 arch/arm/include/asm/arch-exynos/clock.h |  326 ++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-exynos/cpu.h   |   53 ++++-
 arch/arm/include/asm/arch-exynos/gpio.h  |   32 +++
 4 files changed, 605 insertions(+), 15 deletions(-)
Minkyu Kang - Jan. 11, 2012, 10:11 a.m.
Dear Chander Kashyap,

On 9 January 2012 15:40, Chander Kashyap <chander.kashyap@linaro.org> wrote:
> Samsung's ARM Cortex-A15 based SoCs are known as Exynos5 series of
> SoCs. This patch adds the support for Exynos5.
>
> Signed-off-by: Chander Kashyap <chander.kashyap@linaro.org>
> ---
> Changes for v2:
>        - This patch was part of "EXYNOS: Add SMDK5250 board support"
>        - Now it is seprated as SoC support.
>
>  arch/arm/cpu/armv7/exynos/clock.c        |  209 +++++++++++++++++++-
>  arch/arm/include/asm/arch-exynos/clock.h |  326 ++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/cpu.h   |   53 ++++-
>  arch/arm/include/asm/arch-exynos/gpio.h  |   32 +++
>  4 files changed, 605 insertions(+), 15 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
> index 6d97b99..fd050b1 100644
> --- a/arch/arm/include/asm/arch-exynos/cpu.h
> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
> @@ -22,6 +22,8 @@
>  #ifndef _EXYNOS4_CPU_H
>  #define _EXYNOS4_CPU_H
>
> +#define DEVICE_NOT_AVAILABLE           0
> +
>  #define EXYNOS4_ADDR_BASE              0x10000000
>
>  /* EXYNOS4 */
> @@ -46,7 +48,31 @@
>  #define EXYNOS4_ADC_BASE               0x13910000
>  #define EXYNOS4_PWMTIMER_BASE          0x139D0000
>  #define EXYNOS4_MODEM_BASE             0x13A00000
> -#define EXYNOS4_USBPHY_CONTROL          0x10020704
> +#define EXYNOS4_USBPHY_CONTROL         0x10020704
> +
> +/* EXYNOS5 */
> +#define EXYNOS5_PRO_ID                 0x10000000
> +#define EXYNOS5_CLOCK_BASE             0x10010000
> +#define EXYNOS5_POWER_BASE             0x10040000
> +#define EXYNOS5_SWRESET                        0x10040400
> +#define EXYNOS5_SYSREG_BASE            0x10050000
> +#define EXYNOS5_WATCHDOG_BASE          0x101D0000
> +#define EXYNOS5_GPIO_PART1_BASE                0x11400000

just one part?
According to your patch, exynos5 support 20 banks of gpio right?
I think it's too small.
Please check.

> +#define EXYNOS5_MMC_BASE               0x12200000
> +#define EXYNOS5_SROMC_BASE             0x12250000
> +#define EXYNOS5_USBOTG_BASE            0x12480000
> +#define EXYNOS5_USBPHY_BASE            0x12480000
> +#define EXYNOS5_UART_BASE              0x12C00000
> +#define EXYNOS5_PWMTIMER_BASE          0x12DD0000
> +#define EXYNOS5_DMC_CTRL_BASE          0x10DD0000
> +#define EXYNOS5_PHY0_CTRL_BASE         0x10C00000
> +#define EXYNOS5_PHY1_CTRL_BASE         0x10C10000

What are PHY0 and PHY1?

> +#define EXYNOS5_FIMD_BASE              0x14400000

And please sort this list.

> +
> +#define EXYNOS5_ADC_BASE               DEVICE_NOT_AVAILABLE
> +#define EXYNOS5_GPIO_PART2_BASE                DEVICE_NOT_AVAILABLE
> +#define EXYNOS5_GPIO_PART3_BASE                DEVICE_NOT_AVAILABLE
> +#define EXYNOS5_MODEM_BASE             DEVICE_NOT_AVAILABLE
>
>  #ifndef __ASSEMBLY__
>  #include <asm/io.h>
> @@ -59,9 +85,22 @@ static inline int s5p_get_cpu_rev(void)
>        return s5p_cpu_rev;
>  }
>
> +#define IS_SAMSUNG_TYPE(type, id)                      \
> +static inline int cpu_is_##type(void)                  \
> +{                                                      \
> +       return s5p_cpu_id == id ? 1 : 0;                \
> +}
> +
> +IS_SAMSUNG_TYPE(exynos4, 0xc210)
> +IS_SAMSUNG_TYPE(exynos5, 0xc520)
> +
>  static inline void s5p_set_cpu_id(void)
>  {
> -       s5p_cpu_id = readl(EXYNOS4_PRO_ID);
> +       if (cpu_is_exynos5())
> +               s5p_cpu_id = readl(EXYNOS5_PRO_ID);
> +       else
> +               s5p_cpu_id = readl(EXYNOS4_PRO_ID);

Hm.. this is right but,
Since base addresses are same, just do "s5p_cpu_id = readl(EXYNOS4_PRO_ID);"

> +
>        s5p_cpu_id = (0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12));
>
>        /*
> @@ -76,19 +115,13 @@ static 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(exynos4, 0xc210)

So.. no need to move.

> -
>  #define SAMSUNG_BASE(device, base)                             \
>  static inline unsigned int samsung_get_base_##device(void)     \
>  {                                                              \
>        if (cpu_is_exynos4())                                   \
>                return EXYNOS4_##base;                          \
> +       else if (cpu_is_exynos5())                              \
> +               return EXYNOS5_##base;                          \
>        else                                                    \
>                return 0;                                       \
>  }
> diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h
> index 9863a12..a5a09ec 100644
> --- a/arch/arm/include/asm/arch-exynos/gpio.h
> +++ b/arch/arm/include/asm/arch-exynos/gpio.h
> @@ -75,6 +75,29 @@ struct exynos4_gpio_part2 {
>        struct s5p_gpio_bank x3;
>  };
>
> +struct exynos5_gpio_part1 {
> +       struct s5p_gpio_bank a0;
> +       struct s5p_gpio_bank a1;
> +       struct s5p_gpio_bank a2;
> +       struct s5p_gpio_bank b0;
> +       struct s5p_gpio_bank b1;
> +       struct s5p_gpio_bank b2;
> +       struct s5p_gpio_bank b3;
> +       struct s5p_gpio_bank c0;
> +       struct s5p_gpio_bank c1;
> +       struct s5p_gpio_bank c2;
> +       struct s5p_gpio_bank c3;
> +       struct s5p_gpio_bank d0;
> +       struct s5p_gpio_bank d1;
> +       struct s5p_gpio_bank y0;
> +       struct s5p_gpio_bank y1;
> +       struct s5p_gpio_bank y2;
> +       struct s5p_gpio_bank y3;
> +       struct s5p_gpio_bank y4;
> +       struct s5p_gpio_bank y5;
> +       struct s5p_gpio_bank y6;
> +};

Please move it to under the exynos4_gpio_part3.

> +
>  struct exynos4_gpio_part3 {
>        struct s5p_gpio_bank z;
>  };
> @@ -107,8 +130,17 @@ void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode);
>            - EXYNOS4_GPIO_PART2_BASE) / sizeof(struct s5p_gpio_bank)) \
>          * GPIO_PER_BANK) + pin) + GPIO_PART1_MAX)
>
> +#define exynos5_gpio_part1_get_nr(bank, pin) \

If it support just one part then remove part1. (exynos5_gpio_get_nr)

> +       ((((((unsigned int) &(((struct exynos5_gpio_part1 *) \
> +                              EXYNOS5_GPIO_PART1_BASE)->bank)) \
> +           - EXYNOS5_GPIO_PART1_BASE) / sizeof(struct s5p_gpio_bank)) \
> +         * GPIO_PER_BANK) + pin)
> +
>  static inline unsigned int s5p_gpio_base(int nr)
>  {
> +       if (cpu_is_exynos5())
> +               return EXYNOS5_GPIO_PART1_BASE;
> +
>        if (nr < GPIO_PART1_MAX)
>                return EXYNOS4_GPIO_PART1_BASE;
>        else
> --
> 1.7.5.4
>

Thanks.
Minkyu Kang.
Chander Kashyap - Jan. 11, 2012, 10:48 a.m.
Dear Minkyu Kang,

On 11 January 2012 15:41, Minkyu Kang <promsoft@gmail.com> wrote:
> Dear Chander Kashyap,
>
> On 9 January 2012 15:40, Chander Kashyap <chander.kashyap@linaro.org> wrote:
>> Samsung's ARM Cortex-A15 based SoCs are known as Exynos5 series of
>> SoCs. This patch adds the support for Exynos5.
>>
>> Signed-off-by: Chander Kashyap <chander.kashyap@linaro.org>
>> ---
>> Changes for v2:
>>        - This patch was part of "EXYNOS: Add SMDK5250 board support"
>>        - Now it is seprated as SoC support.
>>
>>  arch/arm/cpu/armv7/exynos/clock.c        |  209 +++++++++++++++++++-
>>  arch/arm/include/asm/arch-exynos/clock.h |  326 ++++++++++++++++++++++++++++++
>>  arch/arm/include/asm/arch-exynos/cpu.h   |   53 ++++-
>>  arch/arm/include/asm/arch-exynos/gpio.h  |   32 +++
>>  4 files changed, 605 insertions(+), 15 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
>> index 6d97b99..fd050b1 100644
>> --- a/arch/arm/include/asm/arch-exynos/cpu.h
>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
>> @@ -22,6 +22,8 @@
>>  #ifndef _EXYNOS4_CPU_H
>>  #define _EXYNOS4_CPU_H
>>
>> +#define DEVICE_NOT_AVAILABLE           0
>> +
>>  #define EXYNOS4_ADDR_BASE              0x10000000
>>
>>  /* EXYNOS4 */
>> @@ -46,7 +48,31 @@
>>  #define EXYNOS4_ADC_BASE               0x13910000
>>  #define EXYNOS4_PWMTIMER_BASE          0x139D0000
>>  #define EXYNOS4_MODEM_BASE             0x13A00000
>> -#define EXYNOS4_USBPHY_CONTROL          0x10020704
>> +#define EXYNOS4_USBPHY_CONTROL         0x10020704
>> +
>> +/* EXYNOS5 */
>> +#define EXYNOS5_PRO_ID                 0x10000000
>> +#define EXYNOS5_CLOCK_BASE             0x10010000
>> +#define EXYNOS5_POWER_BASE             0x10040000
>> +#define EXYNOS5_SWRESET                        0x10040400
>> +#define EXYNOS5_SYSREG_BASE            0x10050000
>> +#define EXYNOS5_WATCHDOG_BASE          0x101D0000
>> +#define EXYNOS5_GPIO_PART1_BASE                0x11400000
>
> just one part?
> According to your patch, exynos5 support 20 banks of gpio right?
> I think it's too small.
> Please check.
Yes this list is not complete. Only uart, srom and mmc gpio are listed.
I will Populate the list.
>
>> +#define EXYNOS5_MMC_BASE               0x12200000
>> +#define EXYNOS5_SROMC_BASE             0x12250000
>> +#define EXYNOS5_USBOTG_BASE            0x12480000
>> +#define EXYNOS5_USBPHY_BASE            0x12480000
>> +#define EXYNOS5_UART_BASE              0x12C00000
>> +#define EXYNOS5_PWMTIMER_BASE          0x12DD0000
>> +#define EXYNOS5_DMC_CTRL_BASE          0x10DD0000
>> +#define EXYNOS5_PHY0_CTRL_BASE         0x10C00000
>> +#define EXYNOS5_PHY1_CTRL_BASE         0x10C10000
>
> What are PHY0 and PHY1?
there are two DMC PHY control registers
>
>> +#define EXYNOS5_FIMD_BASE              0x14400000
>
> And please sort this list.
Ok
>
>> +
>> +#define EXYNOS5_ADC_BASE               DEVICE_NOT_AVAILABLE
>> +#define EXYNOS5_GPIO_PART2_BASE                DEVICE_NOT_AVAILABLE
>> +#define EXYNOS5_GPIO_PART3_BASE                DEVICE_NOT_AVAILABLE
>> +#define EXYNOS5_MODEM_BASE             DEVICE_NOT_AVAILABLE
>>
>>  #ifndef __ASSEMBLY__
>>  #include <asm/io.h>
>> @@ -59,9 +85,22 @@ static inline int s5p_get_cpu_rev(void)
>>        return s5p_cpu_rev;
>>  }
>>
>> +#define IS_SAMSUNG_TYPE(type, id)                      \
>> +static inline int cpu_is_##type(void)                  \
>> +{                                                      \
>> +       return s5p_cpu_id == id ? 1 : 0;                \
>> +}
>> +
>> +IS_SAMSUNG_TYPE(exynos4, 0xc210)
>> +IS_SAMSUNG_TYPE(exynos5, 0xc520)
>> +
>>  static inline void s5p_set_cpu_id(void)
>>  {
>> -       s5p_cpu_id = readl(EXYNOS4_PRO_ID);
>> +       if (cpu_is_exynos5())
>> +               s5p_cpu_id = readl(EXYNOS5_PRO_ID);
>> +       else
>> +               s5p_cpu_id = readl(EXYNOS4_PRO_ID);
>
> Hm.. this is right but,
> Since base addresses are same, just do "s5p_cpu_id = readl(EXYNOS4_PRO_ID);"
ok
>
>> +
>>        s5p_cpu_id = (0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12));
>>
>>        /*
>> @@ -76,19 +115,13 @@ static 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(exynos4, 0xc210)
>
> So.. no need to move.
I got it
>
>> -
>>  #define SAMSUNG_BASE(device, base)                             \
>>  static inline unsigned int samsung_get_base_##device(void)     \
>>  {                                                              \
>>        if (cpu_is_exynos4())                                   \
>>                return EXYNOS4_##base;                          \
>> +       else if (cpu_is_exynos5())                              \
>> +               return EXYNOS5_##base;                          \
>>        else                                                    \
>>                return 0;                                       \
>>  }
>> diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h
>> index 9863a12..a5a09ec 100644
>> --- a/arch/arm/include/asm/arch-exynos/gpio.h
>> +++ b/arch/arm/include/asm/arch-exynos/gpio.h
>> @@ -75,6 +75,29 @@ struct exynos4_gpio_part2 {
>>        struct s5p_gpio_bank x3;
>>  };
>>
>> +struct exynos5_gpio_part1 {
>> +       struct s5p_gpio_bank a0;
>> +       struct s5p_gpio_bank a1;
>> +       struct s5p_gpio_bank a2;
>> +       struct s5p_gpio_bank b0;
>> +       struct s5p_gpio_bank b1;
>> +       struct s5p_gpio_bank b2;
>> +       struct s5p_gpio_bank b3;
>> +       struct s5p_gpio_bank c0;
>> +       struct s5p_gpio_bank c1;
>> +       struct s5p_gpio_bank c2;
>> +       struct s5p_gpio_bank c3;
>> +       struct s5p_gpio_bank d0;
>> +       struct s5p_gpio_bank d1;
>> +       struct s5p_gpio_bank y0;
>> +       struct s5p_gpio_bank y1;
>> +       struct s5p_gpio_bank y2;
>> +       struct s5p_gpio_bank y3;
>> +       struct s5p_gpio_bank y4;
>> +       struct s5p_gpio_bank y5;
>> +       struct s5p_gpio_bank y6;
>> +};
>
> Please move it to under the exynos4_gpio_part3.
ok
>
>> +
>>  struct exynos4_gpio_part3 {
>>        struct s5p_gpio_bank z;
>>  };
>> @@ -107,8 +130,17 @@ void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode);
>>            - EXYNOS4_GPIO_PART2_BASE) / sizeof(struct s5p_gpio_bank)) \
>>          * GPIO_PER_BANK) + pin) + GPIO_PART1_MAX)
>>
>> +#define exynos5_gpio_part1_get_nr(bank, pin) \
>
> If it support just one part then remove part1. (exynos5_gpio_get_nr)
>
ok
>> +       ((((((unsigned int) &(((struct exynos5_gpio_part1 *) \
>> +                              EXYNOS5_GPIO_PART1_BASE)->bank)) \
>> +           - EXYNOS5_GPIO_PART1_BASE) / sizeof(struct s5p_gpio_bank)) \
>> +         * GPIO_PER_BANK) + pin)
>> +
>>  static inline unsigned int s5p_gpio_base(int nr)
>>  {
>> +       if (cpu_is_exynos5())
>> +               return EXYNOS5_GPIO_PART1_BASE;
>> +
>>        if (nr < GPIO_PART1_MAX)
>>                return EXYNOS4_GPIO_PART1_BASE;
>>        else
>> --
>> 1.7.5.4
>>
>
> Thanks.
> Minkyu Kang.
> --
> from. prom.
> www.promsoft.net

Patch

diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 4d92c53..02f64bb 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -92,6 +92,72 @@  static unsigned long exynos4_get_pll_clk(int pllreg)
 	return fout;
 }
 
+/* exynos5: return pll clock frequency */
+static unsigned long exynos5_get_pll_clk(int pllreg)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_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 & 0xfff;
+		/* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
+		fout = (m + k / 1024) * (freq / (p * (1 << s)));
+	} else {
+		if (s < 1)
+			s = 1;
+		/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
+		fout = m * (freq / (p * (1 << (s - 1))));
+	}
+
+	return fout;
+}
+
 /* exynos4: return ARM clock frequency */
 static unsigned long exynos4_get_arm_clk(void)
 {
@@ -114,6 +180,28 @@  static unsigned long exynos4_get_arm_clk(void)
 	return armclk;
 }
 
+/* exynos5: return ARM clock frequency */
+static unsigned long exynos5_get_arm_clk(void)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+	unsigned long div;
+	unsigned long armclk;
+	unsigned int arm_ratio;
+	unsigned int arm2_ratio;
+
+	div = readl(&clk->div_cpu0);
+
+	/* ARM_RATIO: [2:0], ARM2_RATIO: [30:28] */
+	arm_ratio = (div >> 0) & 0x7;
+	arm2_ratio = (div >> 28) & 0x7;
+
+	armclk = get_pll_clk(APLL) / (arm_ratio + 1);
+	armclk /= (arm2_ratio + 1);
+
+	return armclk;
+}
+
 /* exynos4: return pwm clock frequency */
 static unsigned long exynos4_get_pwm_clk(void)
 {
@@ -157,6 +245,28 @@  static unsigned long exynos4_get_pwm_clk(void)
 	return pclk;
 }
 
+/* exynos5: return pwm clock frequency */
+static unsigned long exynos5_get_pwm_clk(void)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+	unsigned long pclk, sclk;
+	unsigned int sel;
+	unsigned int ratio;
+
+	/*
+	 * CLK_DIV_PERIC3
+	 * PWM_RATIO [3:0]
+	 */
+	ratio = readl(&clk->div_peric3);
+	ratio = ratio & 0xf;
+	sclk = get_pll_clk(MPLL);
+
+	pclk = sclk / (ratio + 1);
+
+	return pclk;
+}
+
 /* exynos4: return uart clock frequency */
 static unsigned long exynos4_get_uart_clk(int dev_index)
 {
@@ -204,6 +314,53 @@  static unsigned long exynos4_get_uart_clk(int dev_index)
 	return uclk;
 }
 
+/* exynos5: return uart clock frequency */
+static unsigned long exynos5_get_uart_clk(int dev_index)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+	unsigned long uclk, sclk;
+	unsigned int sel;
+	unsigned int ratio;
+
+	/*
+	 * CLK_SRC_PERIC0
+	 * UART0_SEL [3:0]
+	 * UART1_SEL [7:4]
+	 * UART2_SEL [8:11]
+	 * UART3_SEL [12:15]
+	 * UART4_SEL [16:19]
+	 * UART5_SEL [23:20]
+	 */
+	sel = readl(&clk->src_peric0);
+	sel = (sel >> (dev_index << 2)) & 0xf;
+
+	if (sel == 0x6)
+		sclk = get_pll_clk(MPLL);
+	else if (sel == 0x7)
+		sclk = get_pll_clk(EPLL);
+	else if (sel == 0x8)
+		sclk = get_pll_clk(VPLL);
+	else
+		return 0;
+
+	/*
+	 * CLK_DIV_PERIC0
+	 * UART0_RATIO [3:0]
+	 * UART1_RATIO [7:4]
+	 * UART2_RATIO [8:11]
+	 * UART3_RATIO [12:15]
+	 * UART4_RATIO [16:19]
+	 * UART5_RATIO [23:20]
+	 */
+	ratio = readl(&clk->div_peric0);
+	ratio = (ratio >> (dev_index << 2)) & 0xf;
+
+	uclk = sclk / (ratio + 1);
+
+	return uclk;
+}
+
 /* exynos4: set the mmc clock */
 static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
 {
@@ -231,27 +388,69 @@  static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
 	writel(val, addr);
 }
 
+/* exynos5: set the mmc clock */
+static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+	unsigned int addr;
+	unsigned int val;
+
+	/*
+	 * CLK_DIV_FSYS1
+	 * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24]
+	 * CLK_DIV_FSYS2
+	 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24]
+	 */
+	if (dev_index < 2) {
+		addr = (unsigned int)&clk->div_fsys1;
+	} else {
+		addr = (unsigned int)&clk->div_fsys2;
+		dev_index -= 2;
+	}
+
+	val = readl(addr);
+	val &= ~(0xff << ((dev_index << 4) + 8));
+	val |= (div & 0xff) << ((dev_index << 4) + 8);
+	writel(val, addr);
+}
+
 unsigned long get_pll_clk(int pllreg)
 {
-	return exynos4_get_pll_clk(pllreg);
+	if (cpu_is_exynos5())
+		return exynos5_get_pll_clk(pllreg);
+	else
+		return exynos4_get_pll_clk(pllreg);
 }
 
 unsigned long get_arm_clk(void)
 {
-	return exynos4_get_arm_clk();
+	if (cpu_is_exynos5())
+		return exynos5_get_arm_clk();
+	else
+		return exynos4_get_arm_clk();
 }
 
 unsigned long get_pwm_clk(void)
 {
-	return exynos4_get_pwm_clk();
+	if (cpu_is_exynos5())
+		return exynos5_get_pwm_clk();
+	else
+		return exynos4_get_pwm_clk();
 }
 
 unsigned long get_uart_clk(int dev_index)
 {
-	return exynos4_get_uart_clk(dev_index);
+	if (cpu_is_exynos5())
+		return exynos5_get_uart_clk(dev_index);
+	else
+		return exynos4_get_uart_clk(dev_index);
 }
 
 void set_mmc_clk(int dev_index, unsigned int div)
 {
-	exynos4_set_mmc_clk(dev_index, div);
+	if (cpu_is_exynos5())
+		exynos5_set_mmc_clk(dev_index, div);
+	else
+		exynos4_set_mmc_clk(dev_index, div);
 }
diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h
index 483c911..0cddf5e 100644
--- a/arch/arm/include/asm/arch-exynos/clock.h
+++ b/arch/arm/include/asm/arch-exynos/clock.h
@@ -250,6 +250,332 @@  struct exynos4_clock {
 	unsigned int	div_iem_l2;
 	unsigned int	div_iem_l1;
 };
+
+struct exynos5_clock {
+	unsigned int	apll_lock;
+	unsigned char	res1[0xfc];
+	unsigned int	apll_con0;
+	unsigned int	apll_con1;
+	unsigned char	res2[0xf8];
+	unsigned int	src_cpu;
+	unsigned char	res3[0x1fc];
+	unsigned int	mux_stat_cpu;
+	unsigned char	res4[0xfc];
+	unsigned int	div_cpu0;
+	unsigned int	div_cpu1;
+	unsigned char	res5[0xf8];
+	unsigned int	div_stat_cpu0;
+	unsigned int	div_stat_cpu1;
+	unsigned char	res6[0x1f8];
+	unsigned int	gate_sclk_cpu;
+	unsigned char	res7[0x1fc];
+	unsigned int	clkout_cmu_cpu;
+	unsigned int	clkout_cmu_cpu_div_stat;
+	unsigned char	res8[0x5f8];
+	unsigned int	armclk_stopctrl;
+	unsigned int	atclk_stopctrl;
+	unsigned char	res9[0x8];
+	unsigned int	parityfail_status;
+	unsigned int	parityfail_clear;
+	unsigned char	res10[0x8];
+	unsigned int	pwr_ctrl;
+	unsigned int	pwr_ctr2;
+	unsigned char	res11[0xd8];
+	unsigned int	apll_con0_l8;
+	unsigned int	apll_con0_l7;
+	unsigned int	apll_con0_l6;
+	unsigned int	apll_con0_l5;
+	unsigned int	apll_con0_l4;
+	unsigned int	apll_con0_l3;
+	unsigned int	apll_con0_l2;
+	unsigned int	apll_con0_l1;
+	unsigned int	iem_control;
+	unsigned char	res12[0xdc];
+	unsigned int	apll_con1_l8;
+	unsigned int	apll_con1_l7;
+	unsigned int	apll_con1_l6;
+	unsigned int	apll_con1_l5;
+	unsigned int	apll_con1_l4;
+	unsigned int	apll_con1_l3;
+	unsigned int	apll_con1_l2;
+	unsigned int	apll_con1_l1;
+	unsigned char	res13[0xe0];
+	unsigned int	div_iem_l8;
+	unsigned int	div_iem_l7;
+	unsigned int	div_iem_l6;
+	unsigned int	div_iem_l5;
+	unsigned int	div_iem_l4;
+	unsigned int	div_iem_l3;
+	unsigned int	div_iem_l2;
+	unsigned int	div_iem_l1;
+	unsigned char	res14[0x2ce0];
+	unsigned int	mpll_lock;
+	unsigned char	res15[0xfc];
+	unsigned int	mpll_con0;
+	unsigned int	mpll_con1;
+	unsigned char	res16[0xf8];
+	unsigned int	src_core0;
+	unsigned int	src_core1;
+	unsigned char	res17[0xf8];
+	unsigned int	src_mask_core;
+	unsigned char	res18[0x100];
+	unsigned int	mux_stat_core1;
+	unsigned char	res19[0xf8];
+	unsigned int	div_core0;
+	unsigned int	div_core1;
+	unsigned char	res20[0xf8];
+	unsigned int	div_stat_core0;
+	unsigned int	div_stat_core1;
+	unsigned char	res21[0x2f8];
+	unsigned int	gate_ip_core;
+	unsigned char	res22[0xfc];
+	unsigned int	clkout_cmu_core;
+	unsigned int	clkout_cmu_core_div_stat;
+	unsigned char	res23[0x5f8];
+	unsigned int	dcgidx_map0;
+	unsigned int	dcgidx_map1;
+	unsigned int	dcgidx_map2;
+	unsigned char	res24[0x14];
+	unsigned int	dcgperf_map0;
+	unsigned int	dcgperf_map1;
+	unsigned char	res25[0x18];
+	unsigned int	dvcidx_map;
+	unsigned char	res26[0x1c];
+	unsigned int	freq_cpu;
+	unsigned int	freq_dpm;
+	unsigned char	res27[0x18];
+	unsigned int	dvsemclk_en;
+	unsigned int	maxperf;
+	unsigned char	res28[0x3478];
+	unsigned int	div_acp;
+	unsigned char	res29[0xfc];
+	unsigned int	div_stat_acp;
+	unsigned char	res30[0x1fc];
+	unsigned int	gate_ip_acp;
+	unsigned char	res31[0x1fc];
+	unsigned int	clkout_cmu_acp;
+	unsigned int	clkout_cmu_acp_div_stat;
+	unsigned char	res32[0x38f8];
+	unsigned int	div_isp0;
+	unsigned int	div_isp1;
+	unsigned int	div_isp2;
+	unsigned char	res33[0xf4];
+	unsigned int	div_stat_isp0;
+	unsigned int	div_stat_isp1;
+	unsigned int	div_stat_isp2;
+	unsigned char	res34[0x3f4];
+	unsigned int	gate_ip_isp0;
+	unsigned int	gate_ip_isp1;
+	unsigned char	res35[0xf8];
+	unsigned int	gate_sclk_isp;
+	unsigned char	res36[0xc];
+	unsigned int	mcuisp_pwr_ctrl;
+	unsigned char	res37[0xec];
+	unsigned int	clkout_cmu_isp;
+	unsigned int	clkout_cmu_isp_div_stat;
+	unsigned char	res38[0x3618];
+	unsigned int	cpll_lock;
+	unsigned char	res39[0xc];
+	unsigned int	epll_lock;
+	unsigned char	res40[0xc];
+	unsigned int	vpll_lock;
+	unsigned char	res41[0xdc];
+	unsigned int	cpll_con0;
+	unsigned int	cpll_con1;
+	unsigned char	res42[0x8];
+	unsigned int	epll_con0;
+	unsigned int	epll_con1;
+	unsigned int	epll_con2;
+	unsigned char	res43[0x4];
+	unsigned int	vpll_con0;
+	unsigned int	vpll_con1;
+	unsigned int	vpll_con8;
+	unsigned char	res44[0xc4];
+	unsigned int	src_top0;
+	unsigned int	src_top1;
+	unsigned int	src_top2;
+	unsigned int	src_top3;
+	unsigned int	src_gscl;
+	unsigned int	src_disp0_0;
+	unsigned int	src_disp0_1;
+	unsigned int	src_disp1_0;
+	unsigned int	src_disp1_1;
+	unsigned char	res46[0xc];
+	unsigned int	src_mau;
+	unsigned int	src_fsys;
+	unsigned char	res47[0x8];
+	unsigned int	src_peric0;
+	unsigned int	src_peric1;
+	unsigned char	res48[0x18];
+	unsigned int	sclk_src_isp;
+	unsigned char	res49[0x9c];
+	unsigned int	src_mask_top;
+	unsigned char	res50[0xc];
+	unsigned int	src_mask_gscl;
+	unsigned int	src_mask_disp0_0;
+	unsigned int	src_mask_disp0_1;
+	unsigned int	src_mask_disp1_0;
+	unsigned int	src_mask_disp1_1;
+	unsigned int	src_mask_maudio;
+	unsigned char	res52[0x8];
+	unsigned int	src_mask_fsys;
+	unsigned char	res53[0xc];
+	unsigned int	src_mask_peric0;
+	unsigned int	src_mask_peric1;
+	unsigned char	res54[0x18];
+	unsigned int	src_mask_isp;
+	unsigned char	res55[0x9c];
+	unsigned int	mux_stat_top0;
+	unsigned int	mux_stat_top1;
+	unsigned int	mux_stat_top2;
+	unsigned int	mux_stat_top3;
+	unsigned char	res56[0xf0];
+	unsigned int	div_top0;
+	unsigned int	div_top1;
+	unsigned char	res57[0x8];
+	unsigned int	div_gscl;
+	unsigned int	div_disp0_0;
+	unsigned int	div_disp0_1;
+	unsigned int	div_disp1_0;
+	unsigned int	div_disp1_1;
+	unsigned char	res59[0x8];
+	unsigned int	div_gen;
+	unsigned char	res60[0x4];
+	unsigned int	div_mau;
+	unsigned int	div_fsys0;
+	unsigned int	div_fsys1;
+	unsigned int	div_fsys2;
+	unsigned int	div_fsys3;
+	unsigned int	div_peric0;
+	unsigned int	div_peric1;
+	unsigned int	div_peric2;
+	unsigned int	div_peric3;
+	unsigned int	div_peric4;
+	unsigned int	div_peric5;
+	unsigned char	res61[0x10];
+	unsigned int	sclk_div_isp;
+	unsigned char	res62[0xc];
+	unsigned int	div2_ratio0;
+	unsigned int	div2_ratio1;
+	unsigned char	res63[0x8];
+	unsigned int	div4_ratio;
+	unsigned char	res64[0x6c];
+	unsigned int	div_stat_top0;
+	unsigned int	div_stat_top1;
+	unsigned char	res65[0x8];
+	unsigned int	div_stat_gscl;
+	unsigned int	div_stat_disp0_0;
+	unsigned int	div_stat_disp0_1;
+	unsigned int	div_stat_disp1_0;
+	unsigned int	div_stat_disp1_1;
+	unsigned char	res67[0x8];
+	unsigned int	div_stat_gen;
+	unsigned char	res68[0x4];
+	unsigned int	div_stat_maudio;
+	unsigned int	div_stat_fsys0;
+	unsigned int	div_stat_fsys1;
+	unsigned int	div_stat_fsys2;
+	unsigned int	div_stat_fsys3;
+	unsigned int	div_stat_peric0;
+	unsigned int	div_stat_peric1;
+	unsigned int	div_stat_peric2;
+	unsigned int	div_stat_peric3;
+	unsigned int	div_stat_peric4;
+	unsigned int	div_stat_peric5;
+	unsigned char	res69[0x10];
+	unsigned int	sclk_div_stat_isp;
+	unsigned char	res70[0xc];
+	unsigned int	div2_stat0;
+	unsigned int	div2_stat1;
+	unsigned char	res71[0x8];
+	unsigned int	div4_stat;
+	unsigned char	res72[0x180];
+	unsigned int	gate_top_sclk_disp0;
+	unsigned int	gate_top_sclk_disp1;
+	unsigned int	gate_top_sclk_gen;
+	unsigned char	res74[0xc];
+	unsigned int	gate_top_sclk_mau;
+	unsigned int	gate_top_sclk_fsys;
+	unsigned char	res75[0xc];
+	unsigned int	gate_top_sclk_peric;
+	unsigned char	res76[0x1c];
+	unsigned int	gate_top_sclk_isp;
+	unsigned char	res77[0xac];
+	unsigned int	gate_ip_gscl;
+	unsigned int	gate_ip_disp0;
+	unsigned int	gate_ip_disp1;
+	unsigned int	gate_ip_mfc;
+	unsigned int	gate_ip_g3d;
+	unsigned int	gate_ip_gen;
+	unsigned char	res79[0xc];
+	unsigned int	gate_ip_fsys;
+	unsigned char	res80[0x4];
+	unsigned int	gate_ip_gps;
+	unsigned int	gate_ip_peric;
+	unsigned char	res81[0xc];
+	unsigned int	gate_ip_peris;
+	unsigned char	res82[0x1c];
+	unsigned int	gate_block;
+	unsigned char	res83[0x7c];
+	unsigned int	clkout_cmu_top;
+	unsigned int	clkout_cmu_top_div_stat;
+	unsigned char	res84[0x37f8];
+	unsigned int	src_lex;
+	unsigned char	res85[0x2fc];
+	unsigned int	div_lex;
+	unsigned char	res86[0xfc];
+	unsigned int	div_stat_lex;
+	unsigned char	res87[0x1fc];
+	unsigned int	gate_ip_lex;
+	unsigned char	res88[0x1fc];
+	unsigned int	clkout_cmu_lex;
+	unsigned int	clkout_cmu_lex_div_stat;
+	unsigned char	res89[0x3af8];
+	unsigned int	div_r0x;
+	unsigned char	res90[0xfc];
+	unsigned int	div_stat_r0x;
+	unsigned char	res91[0x1fc];
+	unsigned int	gate_ip_r0x;
+	unsigned char	res92[0x1fc];
+	unsigned int	clkout_cmu_r0x;
+	unsigned int	clkout_cmu_r0x_div_stat;
+	unsigned char	res94[0x3af8];
+	unsigned int	div_r1x;
+	unsigned char	res95[0xfc];
+	unsigned int	div_stat_r1x;
+	unsigned char	res96[0x1fc];
+	unsigned int	gate_ip_r1x;
+	unsigned char	res97[0x1fc];
+	unsigned int	clkout_cmu_r1x;
+	unsigned int	clkout_cmu_r1x_div_stat;
+	unsigned char	res98[0x3608];
+	unsigned int	bpll_lock;
+	unsigned char	res99[0xfc];
+	unsigned int	bpll_con0;
+	unsigned int	bpll_con1;
+	unsigned char	res100[0xe8];
+	unsigned int	src_cdrex;
+	unsigned char	res101[0x1fc];
+	unsigned int	mux_stat_cdrex;
+	unsigned char	res102[0xfc];
+	unsigned int	div_cdrex;
+	unsigned int	div_cdrex2;
+	unsigned char	res103[0xf8];
+	unsigned int	div_stat_cdrex;
+	unsigned char	res104[0x2fc];
+	unsigned int	gate_ip_cdrex;
+	unsigned char	res105[0xc];
+	unsigned int	c2c_monitor;
+	unsigned int	dmc_pwr_ctrl;
+	unsigned char	res106[0x4];
+	unsigned int	drex2_pause;
+	unsigned char	res107[0xe0];
+	unsigned int	clkout_cmu_cdrex;
+	unsigned int	clkout_cmu_cdrex_div_stat;
+	unsigned char	res108[0x8];
+	unsigned int	lpddr3phy_ctrl;
+	unsigned char	res109[0xf5f8];
+};
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
index 6d97b99..fd050b1 100644
--- a/arch/arm/include/asm/arch-exynos/cpu.h
+++ b/arch/arm/include/asm/arch-exynos/cpu.h
@@ -22,6 +22,8 @@ 
 #ifndef _EXYNOS4_CPU_H
 #define _EXYNOS4_CPU_H
 
+#define DEVICE_NOT_AVAILABLE		0
+
 #define EXYNOS4_ADDR_BASE		0x10000000
 
 /* EXYNOS4 */
@@ -46,7 +48,31 @@ 
 #define EXYNOS4_ADC_BASE		0x13910000
 #define EXYNOS4_PWMTIMER_BASE		0x139D0000
 #define EXYNOS4_MODEM_BASE		0x13A00000
-#define EXYNOS4_USBPHY_CONTROL          0x10020704
+#define EXYNOS4_USBPHY_CONTROL		0x10020704
+
+/* EXYNOS5 */
+#define EXYNOS5_PRO_ID			0x10000000
+#define EXYNOS5_CLOCK_BASE		0x10010000
+#define EXYNOS5_POWER_BASE		0x10040000
+#define EXYNOS5_SWRESET			0x10040400
+#define EXYNOS5_SYSREG_BASE		0x10050000
+#define EXYNOS5_WATCHDOG_BASE		0x101D0000
+#define EXYNOS5_GPIO_PART1_BASE		0x11400000
+#define EXYNOS5_MMC_BASE		0x12200000
+#define EXYNOS5_SROMC_BASE		0x12250000
+#define EXYNOS5_USBOTG_BASE		0x12480000
+#define EXYNOS5_USBPHY_BASE		0x12480000
+#define EXYNOS5_UART_BASE		0x12C00000
+#define EXYNOS5_PWMTIMER_BASE		0x12DD0000
+#define EXYNOS5_DMC_CTRL_BASE		0x10DD0000
+#define EXYNOS5_PHY0_CTRL_BASE		0x10C00000
+#define EXYNOS5_PHY1_CTRL_BASE		0x10C10000
+#define EXYNOS5_FIMD_BASE		0x14400000
+
+#define EXYNOS5_ADC_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5_GPIO_PART2_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5_GPIO_PART3_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5_MODEM_BASE		DEVICE_NOT_AVAILABLE
 
 #ifndef __ASSEMBLY__
 #include <asm/io.h>
@@ -59,9 +85,22 @@  static inline int s5p_get_cpu_rev(void)
 	return s5p_cpu_rev;
 }
 
+#define IS_SAMSUNG_TYPE(type, id)			\
+static inline int cpu_is_##type(void)			\
+{							\
+	return s5p_cpu_id == id ? 1 : 0;		\
+}
+
+IS_SAMSUNG_TYPE(exynos4, 0xc210)
+IS_SAMSUNG_TYPE(exynos5, 0xc520)
+
 static inline void s5p_set_cpu_id(void)
 {
-	s5p_cpu_id = readl(EXYNOS4_PRO_ID);
+	if (cpu_is_exynos5())
+		s5p_cpu_id = readl(EXYNOS5_PRO_ID);
+	else
+		s5p_cpu_id = readl(EXYNOS4_PRO_ID);
+
 	s5p_cpu_id = (0xC000 | ((s5p_cpu_id & 0x00FFF000) >> 12));
 
 	/*
@@ -76,19 +115,13 @@  static 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(exynos4, 0xc210)
-
 #define SAMSUNG_BASE(device, base)				\
 static inline unsigned int samsung_get_base_##device(void)	\
 {								\
 	if (cpu_is_exynos4())					\
 		return EXYNOS4_##base;				\
+	else if (cpu_is_exynos5())				\
+		return EXYNOS5_##base;				\
 	else							\
 		return 0;					\
 }
diff --git a/arch/arm/include/asm/arch-exynos/gpio.h b/arch/arm/include/asm/arch-exynos/gpio.h
index 9863a12..a5a09ec 100644
--- a/arch/arm/include/asm/arch-exynos/gpio.h
+++ b/arch/arm/include/asm/arch-exynos/gpio.h
@@ -75,6 +75,29 @@  struct exynos4_gpio_part2 {
 	struct s5p_gpio_bank x3;
 };
 
+struct exynos5_gpio_part1 {
+	struct s5p_gpio_bank a0;
+	struct s5p_gpio_bank a1;
+	struct s5p_gpio_bank a2;
+	struct s5p_gpio_bank b0;
+	struct s5p_gpio_bank b1;
+	struct s5p_gpio_bank b2;
+	struct s5p_gpio_bank b3;
+	struct s5p_gpio_bank c0;
+	struct s5p_gpio_bank c1;
+	struct s5p_gpio_bank c2;
+	struct s5p_gpio_bank c3;
+	struct s5p_gpio_bank d0;
+	struct s5p_gpio_bank d1;
+	struct s5p_gpio_bank y0;
+	struct s5p_gpio_bank y1;
+	struct s5p_gpio_bank y2;
+	struct s5p_gpio_bank y3;
+	struct s5p_gpio_bank y4;
+	struct s5p_gpio_bank y5;
+	struct s5p_gpio_bank y6;
+};
+
 struct exynos4_gpio_part3 {
 	struct s5p_gpio_bank z;
 };
@@ -107,8 +130,17 @@  void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode);
 	    - EXYNOS4_GPIO_PART2_BASE) / sizeof(struct s5p_gpio_bank)) \
 	  * GPIO_PER_BANK) + pin) + GPIO_PART1_MAX)
 
+#define exynos5_gpio_part1_get_nr(bank, pin) \
+	((((((unsigned int) &(((struct exynos5_gpio_part1 *) \
+			       EXYNOS5_GPIO_PART1_BASE)->bank)) \
+	    - EXYNOS5_GPIO_PART1_BASE) / sizeof(struct s5p_gpio_bank)) \
+	  * GPIO_PER_BANK) + pin)
+
 static inline unsigned int s5p_gpio_base(int nr)
 {
+	if (cpu_is_exynos5())
+		return EXYNOS5_GPIO_PART1_BASE;
+
 	if (nr < GPIO_PART1_MAX)
 		return EXYNOS4_GPIO_PART1_BASE;
 	else