[PATCH 07/14] MACH SAMSUNG/S3C: Separate S3C24XX clock management

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There are major differences in the clock tree of the S3C24xx family and the
more recent CPUs of the S3C family. Keep the S3C24XX clock routines separate to
avoid a ifdef hell. But also use generic function names to be able to
share drivers among the S3C family.

Signed-off-by: Juergen Beisert <jbe@xxxxxxxxxxxxxx>
---
 arch/arm/mach-samsung/Makefile                   |    2 +-
 arch/arm/mach-samsung/generic.c                  |  117 +------------------
 arch/arm/mach-samsung/include/mach/s3c-clocks.h  |   31 +++++
 arch/arm/mach-samsung/include/mach/s3c-generic.h |   12 +-
 arch/arm/mach-samsung/include/mach/s3c-iomap.h   |   11 +--
 arch/arm/mach-samsung/lowlevel-init.S            |    2 +-
 arch/arm/mach-samsung/s3c24xx-clocks.c           |  137 ++++++++++++++++++++++
 drivers/mci/s3c.c                                |   10 +-
 drivers/serial/serial_s3c24x0.c                  |    2 +-
 drivers/video/s3c24xx.c                          |    4 +-
 10 files changed, 187 insertions(+), 141 deletions(-)
 create mode 100644 arch/arm/mach-samsung/include/mach/s3c-clocks.h
 create mode 100644 arch/arm/mach-samsung/s3c24xx-clocks.c

diff --git a/arch/arm/mach-samsung/Makefile b/arch/arm/mach-samsung/Makefile
index f329cdb..c590180 100644
--- a/arch/arm/mach-samsung/Makefile
+++ b/arch/arm/mach-samsung/Makefile
@@ -1,3 +1,3 @@
 obj-y += generic.o
-obj-$(CONFIG_ARCH_S3C24xx) += gpio-s3c24x0.o
+obj-$(CONFIG_ARCH_S3C24xx) += gpio-s3c24x0.o s3c24xx-clocks.o
 obj-$(CONFIG_S3C24XX_LOW_LEVEL_INIT) += lowlevel-init.o
diff --git a/arch/arm/mach-samsung/generic.c b/arch/arm/mach-samsung/generic.c
index 3c24b1a..3f6e801 100644
--- a/arch/arm/mach-samsung/generic.c
+++ b/arch/arm/mach-samsung/generic.c
@@ -28,100 +28,7 @@
 #include <clock.h>
 #include <io.h>
 #include <mach/s3c-iomap.h>
-
-/**
- * Calculate the current M-PLL clock.
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_mpllclk(void)
-{
-	uint32_t m, p, s, reg_val;
-
-	reg_val = readl(MPLLCON);
-	m = ((reg_val & 0xFF000) >> 12) + 8;
-	p = ((reg_val & 0x003F0) >> 4) + 2;
-	s = reg_val & 0x3;
-#ifdef CONFIG_CPU_S3C2410
-	return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
-#endif
-#ifdef CONFIG_CPU_S3C2440
-	return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s));
-#endif
-}
-
-/**
- * Calculate the current U-PLL clock
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_upllclk(void)
-{
-	uint32_t m, p, s, reg_val;
-
-	reg_val = readl(UPLLCON);
-	m = ((reg_val & 0xFF000) >> 12) + 8;
-	p = ((reg_val & 0x003F0) >> 4) + 2;
-	s = reg_val & 0x3;
-
-	return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
-}
-
-/**
- * Calculate the FCLK frequency used for the ARM CPU core
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_fclk(void)
-{
-	return s3c24xx_get_mpllclk();
-}
-
-/**
- * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral)
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_hclk(void)
-{
-	uint32_t f_clk;
-
-	f_clk = s3c24xx_get_fclk();
-#ifdef CONFIG_CPU_S3C2410
-	if (readl(CLKDIVN) & 0x02)
-		return f_clk >> 1;
-#endif
-#ifdef CONFIG_CPU_S3C2440
-	switch(readl(CLKDIVN) & 0x06) {
-	case 2:
-		return f_clk >> 1;
-	case 4:
-		return f_clk >> 2;	/* TODO consider CAMDIVN */
-	case 6:
-		return f_clk / 3;	/* TODO consider CAMDIVN */
-	}
-#endif
-	return f_clk;
-}
-
-/**
- * Calculate the PCLK frequency used for the slower peripherals
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_pclk(void)
-{
-	uint32_t p_clk;
-
-	p_clk = s3c24xx_get_hclk();
-	if (readl(CLKDIVN) & 0x01)
-		return p_clk >> 1;
-	return p_clk;
-}
-
-/**
- * Calculate the UCLK frequency used by the USB host device
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_uclk(void)
-{
-    return s3c24xx_get_upllclk();
-}
+#include <mach/s3c-generic.h>
 
 /**
  * Calculate the amount of connected and available memory
@@ -169,26 +76,6 @@ uint32_t s3c24x0_get_memory_size(void)
 	return size;
 }
 
-/**
- * Show the user the current clock settings
- */
-int s3c24xx_dump_clocks(void)
-{
-	printf("refclk:  %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000);
-	printf("mpll:    %7d kHz\n", s3c24xx_get_mpllclk() / 1000);
-	printf("upll:    %7d kHz\n", s3c24xx_get_upllclk() / 1000);
-	printf("fclk:    %7d kHz\n", s3c24xx_get_fclk() / 1000);
-	printf("hclk:    %7d kHz\n", s3c24xx_get_hclk() / 1000);
-	printf("pclk:    %7d kHz\n", s3c24xx_get_pclk() / 1000);
-	printf("SDRAM1:   CL%d@%dMHz\n", ((readl(BANKCON6) & 0xc) >> 2) + 2, s3c24xx_get_hclk() / 1000000);
-	if ((readl(BANKCON7) & (0x3 << 15)) == (0x3 << 15))
-		printf("SDRAM2:   CL%d@%dMHz\n", ((readl(BANKCON7) & 0xc) >> 2) + 2,
-			s3c24xx_get_hclk() / 1000000);
-	return 0;
-}
-
-late_initcall(s3c24xx_dump_clocks);
-
 static uint64_t s3c24xx_clocksource_read(void)
 {
 	/* note: its a down counter */
@@ -203,7 +90,7 @@ static struct clocksource cs = {
 
 static int clocksource_init (void)
 {
-	uint32_t p_clk = s3c24xx_get_pclk();
+	uint32_t p_clk = s3c_get_pclk();
 
 	writel(0x00000000, TCON);	/* stop all timers */
 	writel(0x00ffffff, TCFG0);	/* PCLK / (255 + 1) for timer 4 */
diff --git a/arch/arm/mach-samsung/include/mach/s3c-clocks.h b/arch/arm/mach-samsung/include/mach/s3c-clocks.h
new file mode 100644
index 0000000..44b2a6c
--- /dev/null
+++ b/arch/arm/mach-samsung/include/mach/s3c-clocks.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 Juergen Beisert, Pengutronix
+ *
+ * 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.
+ */
+
+#ifndef __MACH_S3C_CLOCKS_H
+# define __MACH_S3C_CLOCKS_H
+
+#ifdef CONFIG_ARCH_S3C24xx
+# define S3C_LOCKTIME (S3C_CLOCK_POWER_BASE)
+# define S3C_MPLLCON (S3C_CLOCK_POWER_BASE + 0x4)
+# define S3C_UPLLCON (S3C_CLOCK_POWER_BASE + 0x8)
+# define S3C_CLKCON (S3C_CLOCK_POWER_BASE + 0xc)
+# define S3C_CLKSLOW (S3C_CLOCK_POWER_BASE + 0x10)
+# define S3C_CLKDIVN (S3C_CLOCK_POWER_BASE + 0x14)
+
+# define S3C_MPLLCON_GET_MDIV(x) ((((x) >> 12) & 0xff) + 8)
+# define S3C_MPLLCON_GET_PDIV(x) ((((x) >> 4) & 0x3f) + 2)
+# define S3C_MPLLCON_GET_SDIV(x) ((x) & 0x3)
+#endif
+
+#endif /* __MACH_S3C_CLOCKS_H */
diff --git a/arch/arm/mach-samsung/include/mach/s3c-generic.h b/arch/arm/mach-samsung/include/mach/s3c-generic.h
index b8abcf1..33f025d 100644
--- a/arch/arm/mach-samsung/include/mach/s3c-generic.h
+++ b/arch/arm/mach-samsung/include/mach/s3c-generic.h
@@ -24,10 +24,10 @@
  * MA 02111-1307 USA
  */
 
-uint32_t s3c24xx_get_mpllclk(void);
-uint32_t s3c24xx_get_upllclk(void);
-uint32_t s3c24xx_get_fclk(void);
-uint32_t s3c24xx_get_hclk(void);
-uint32_t s3c24xx_get_pclk(void);
-uint32_t s3c24xx_get_uclk(void);
+uint32_t s3c_get_mpllclk(void);
+uint32_t s3c_get_upllclk(void);
+uint32_t s3c_get_fclk(void);
+uint32_t s3c_get_hclk(void);
+uint32_t s3c_get_pclk(void);
+uint32_t s3c_get_uclk(void);
 uint32_t s3c24x0_get_memory_size(void);
diff --git a/arch/arm/mach-samsung/include/mach/s3c-iomap.h b/arch/arm/mach-samsung/include/mach/s3c-iomap.h
index a990d80..7cedf6a 100644
--- a/arch/arm/mach-samsung/include/mach/s3c-iomap.h
+++ b/arch/arm/mach-samsung/include/mach/s3c-iomap.h
@@ -25,7 +25,7 @@
 #define S3C2410_USB_HOST_BASE		0x49000000
 #define S3C2410_INTERRUPT_BASE		0x4A000000
 #define S3C2410_DMA_BASE		0x4B000000
-#define S3C24X0_CLOCK_POWER_BASE	0x4C000000
+#define S3C_CLOCK_POWER_BASE		0x4C000000
 #define S3C2410_LCD_BASE		0x4D000000
 #define S3C24X0_NAND_BASE		0x4E000000
 #define S3C24X0_UART_BASE		0x50000000
@@ -40,15 +40,6 @@
 #define S3C2410_SPI_BASE		0x59000000
 #define S3C2410_SDI_BASE		0x5A000000
 
-/* Clock control (direct access) */
-
-#define LOCKTIME (S3C24X0_CLOCK_POWER_BASE)
-#define MPLLCON (S3C24X0_CLOCK_POWER_BASE + 0x4)
-#define UPLLCON (S3C24X0_CLOCK_POWER_BASE + 0x8)
-#define CLKCON (S3C24X0_CLOCK_POWER_BASE + 0xc)
-#define CLKSLOW (S3C24X0_CLOCK_POWER_BASE + 0x10)
-#define CLKDIVN (S3C24X0_CLOCK_POWER_BASE + 0x14)
-
 /* Timer (direct access) */
 #define TCFG0 (S3C24X0_TIMER_BASE + 0x00)
 #define TCFG1 (S3C24X0_TIMER_BASE + 0x04)
diff --git a/arch/arm/mach-samsung/lowlevel-init.S b/arch/arm/mach-samsung/lowlevel-init.S
index 8529283..e2e3fc0 100644
--- a/arch/arm/mach-samsung/lowlevel-init.S
+++ b/arch/arm/mach-samsung/lowlevel-init.S
@@ -77,7 +77,7 @@ routine very early in your board_init_lowlevel routine.
 .globl s3c24x0_pll_init
 s3c24x0_pll_init:
 
-	mov r0, #S3C24X0_CLOCK_POWER_BASE
+	mov r0, #S3C_CLOCK_POWER_BASE
 
 	/* configure internal clock ratio */
 	mov r1, #BOARD_SPECIFIC_CLKDIVN
diff --git a/arch/arm/mach-samsung/s3c24xx-clocks.c b/arch/arm/mach-samsung/s3c24xx-clocks.c
new file mode 100644
index 0000000..beacc76
--- /dev/null
+++ b/arch/arm/mach-samsung/s3c24xx-clocks.c
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <io.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-clocks.h>
+
+/**
+ * Calculate the current M-PLL clock.
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_mpllclk(void)
+{
+	uint32_t m, p, s, reg_val;
+
+	reg_val = readl(S3C_MPLLCON);
+	m = ((reg_val & 0xFF000) >> 12) + 8;
+	p = ((reg_val & 0x003F0) >> 4) + 2;
+	s = reg_val & 0x3;
+#ifdef CONFIG_CPU_S3C2410
+	return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
+#endif
+#ifdef CONFIG_CPU_S3C2440
+	return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s));
+#endif
+}
+
+/**
+ * Calculate the current U-PLL clock
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_upllclk(void)
+{
+	uint32_t m, p, s, reg_val;
+
+	reg_val = readl(S3C_UPLLCON);
+	m = ((reg_val & 0xFF000) >> 12) + 8;
+	p = ((reg_val & 0x003F0) >> 4) + 2;
+	s = reg_val & 0x3;
+
+	return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
+}
+
+/**
+ * Calculate the FCLK frequency used for the ARM CPU core
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_fclk(void)
+{
+	return s3c_get_mpllclk();
+}
+
+/**
+ * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral)
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_hclk(void)
+{
+	uint32_t f_clk;
+
+	f_clk = s3c_get_fclk();
+#ifdef CONFIG_CPU_S3C2410
+	if (readl(S3C_CLKDIVN) & 0x02)
+		return f_clk >> 1;
+#endif
+#ifdef CONFIG_CPU_S3C2440
+	switch(readl(S3C_CLKDIVN) & 0x06) {
+	case 2:
+		return f_clk >> 1;
+	case 4:
+		return f_clk >> 2;	/* TODO consider CAMDIVN */
+	case 6:
+		return f_clk / 3;	/* TODO consider CAMDIVN */
+	}
+#endif
+	return f_clk;
+}
+
+/**
+ * Calculate the PCLK frequency used for the slower peripherals
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_pclk(void)
+{
+	uint32_t p_clk;
+
+	p_clk = s3c_get_hclk();
+	if (readl(S3C_CLKDIVN) & 0x01)
+		return p_clk >> 1;
+	return p_clk;
+}
+
+/**
+ * Calculate the UCLK frequency used by the USB host device
+ * @return Current frequency in Hz
+ */
+uint32_t s3c24_get_uclk(void)
+{
+	return s3c_get_upllclk();
+}
+
+/**
+ * Show the user the current clock settings
+ */
+int s3c24xx_dump_clocks(void)
+{
+	printf("refclk:  %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000);
+	printf("mpll:    %7d kHz\n", s3c_get_mpllclk() / 1000);
+	printf("upll:    %7d kHz\n", s3c_get_upllclk() / 1000);
+	printf("fclk:    %7d kHz\n", s3c_get_fclk() / 1000);
+	printf("hclk:    %7d kHz\n", s3c_get_hclk() / 1000);
+	printf("pclk:    %7d kHz\n", s3c_get_pclk() / 1000);
+	printf("SDRAM1:   CL%d@%dMHz\n", ((readl(BANKCON6) & 0xc) >> 2) + 2, s3c_get_hclk() / 1000000);
+	if ((readl(BANKCON7) & (0x3 << 15)) == (0x3 << 15))
+		printf("SDRAM2:   CL%d@%dMHz\n", ((readl(BANKCON7) & 0xc) >> 2) + 2,
+			s3c_get_hclk() / 1000000);
+	return 0;
+}
+
+late_initcall(s3c24xx_dump_clocks);
diff --git a/drivers/mci/s3c.c b/drivers/mci/s3c.c
index 2a21ca6..ccc8be4 100644
--- a/drivers/mci/s3c.c
+++ b/drivers/mci/s3c.c
@@ -217,7 +217,7 @@ static unsigned s3c_setup_clock_speed(struct device_d *hw_dev, unsigned nc)
 	if (nc == 0)
 		return 0;
 
-	clock = s3c24xx_get_pclk();
+	clock = s3c_get_pclk();
 	/* Calculate the required prescaler value to get the requested frequency */
 	mci_psc = (clock + (nc >> 2)) / nc;
 
@@ -786,8 +786,8 @@ static int s3c_mci_probe(struct device_d *hw_dev)
 	struct s3c_mci_platform_data *pd = hw_dev->platform_data;
 
 	/* TODO replace by the global func: enable the SDI unit clock */
-	writel(readl(S3C24X0_CLOCK_POWER_BASE + 0x0c) | 0x200,
-		S3C24X0_CLOCK_POWER_BASE + 0x0c);
+	writel(readl(S3C_CLOCK_POWER_BASE + 0x0c) | 0x200,
+		S3C_CLOCK_POWER_BASE + 0x0c);
 
 	if (pd == NULL) {
 		pr_err("Missing platform data\n");
@@ -801,8 +801,8 @@ static int s3c_mci_probe(struct device_d *hw_dev)
 	/* feed forward the platform specific values */
 	mci_pdata.voltages = pd->voltages;
 	mci_pdata.host_caps = pd->caps;
-	mci_pdata.f_min = pd->f_min == 0 ? s3c24xx_get_pclk() / 256 : pd->f_min;
-	mci_pdata.f_max = pd->f_max == 0 ? s3c24xx_get_pclk() / 2 : pd->f_max;
+	mci_pdata.f_min = pd->f_min == 0 ? s3c_get_pclk() / 256 : pd->f_min;
+	mci_pdata.f_max = pd->f_max == 0 ? s3c_get_pclk() / 2 : pd->f_max;
 
 	/*
 	 * Start the clock to let the engine and the card finishes its startup
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
index 8e6bb0c..0ca2319 100644
--- a/drivers/serial/serial_s3c24x0.c
+++ b/drivers/serial/serial_s3c24x0.c
@@ -48,7 +48,7 @@ static int s3c24x0_serial_setbaudrate(struct console_device *cdev, int baudrate)
 	unsigned val;
 
 	/* value is calculated so : PCLK / (16 * baudrate) -1 */
-	val = s3c24xx_get_pclk() / (16 * baudrate) - 1;
+	val = s3c_get_pclk() / (16 * baudrate) - 1;
 	writew(val, base + UBRDIV);
 
 	return 0;
diff --git a/drivers/video/s3c24xx.c b/drivers/video/s3c24xx.c
index 75677c3..f6af773 100644
--- a/drivers/video/s3c24xx.c
+++ b/drivers/video/s3c24xx.c
@@ -227,7 +227,7 @@ static int s3cfb_activate_var(struct fb_info *fb_info)
 	/* ensure video output is _off_ */
 	writel(0x00000000, fbi->base + LCDCON1);
 
-	hclk = s3c24xx_get_hclk() / 1000U;	/* hclk in kHz */
+	hclk = s3c_get_hclk() / 1000U;	/* hclk in kHz */
 	div = hclk / PICOS2KHZ(mode->pixclock);
 	if (div < 3)
 		div  = 3;
@@ -339,7 +339,7 @@ static void s3cfb_info(struct device_d *hw_dev)
 	addr3 = readl(fbi->base + LCDSADDR3);
 
 	printf(" Video hardware info:\n");
-	printf("  Video clock is running at %u Hz\n", s3c24xx_get_hclk() / ((GET_CLKVAL(con1) + 1) * 2));
+	printf("  Video clock is running at %u Hz\n", s3c_get_hclk() / ((GET_CLKVAL(con1) + 1) * 2));
 	printf("  Video memory bank starts at 0x%08X\n", GET_LCDBANK(addr1) << 22);
 	printf("  Video memory bank offset: 0x%08X\n", GET_LCDBASEU(addr1));
 	printf("  Video memory end: 0x%08X\n", GET_LCDBASEU(addr2));
-- 
1.7.7.1


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox


[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux