forked from Minki/linux
Samsung S3C24XX to use the common clock framework
- S3C2412, S3C2413, S3C2416 and S3C2443 to use CCF - S3C2410, S3C2440, S3C2442 to use CCF - Remove legacy samsung clock from mach-s3c24xx/ - Some of them are missed from previous pull-request - Clock related sutff got ack from Mike and Tomasz - Created the last commit due to missing changes during re-sorting because this branch is provided as a base to samsung clk tree. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJTeoP9AAoJEA0Cl+kVi2xq+VQP/jKVZmd0FvMeoyoyddUfOxfV b8jKaVbD/lB7vhPc7XGK9waXBdi6Ajdx71VAAfIfcl+m+xp9XTS0eVirWeP9yh6g Xbtqp6QhWJfph1iufI/Tmab075lmHI05iprVP3LIJ8fFVpfHbbMLel9SJEDti+sj +shdWgTdd4Cxl7Y60noo7Y4WEBrC2qpkegC0xut16ZJKdt5WxC4KW2DltC435MB0 b/v7oKLvWr2SvBkDKk7h5aX7z+Ws3ALQ2XfV/CbTkW9LaPFaPqr68V9ZNmHEfeLb Az7aSlktBAAGTjwDHYOuw5w1eHHrZZBOpJfVKFmPVLGNzqkTAzUWMDQJay/LTRDF u9fXtJA2cZBuNmuGdAiE8ZxQwbrLFiPC06Ybie+Qq4LiliCzjBfuB+CuSf7bVw2A jOmU34Cctvyj7JdEZzDDby4baQFgS6NuI5OHnTXjQlfNejtoG0gDSIWWkPm5xr1w c5ADCyq5UzBCmUzhp4KCyxMnqz9BGMxw96PPLKGAlNNw0i1tp8SUFjzaKyDB6yOm I60WDNWGC+T4uoNRvkW8sKGQX7thjtR5KVI0cWvgQbBSiycMoMJcKWAmrckGA1In SPnriO5NpDIOEnV7MQ8pyPLIijhX09xSdDS7wASR9rthC7qnnHmVBjByMQXUi6Th emxN1xC5mM2kT68u/oWB =HX4t -----END PGP SIGNATURE----- Merge tag 's3c24xx-clk' of http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/cleanup Merge "Samsung S3C24XX updates for 3.16" from Kukjin Kim: Samsung S3C24XX to use the common clock framework - S3C2412, S3C2413, S3C2416 and S3C2443 to use CCF - S3C2410, S3C2440, S3C2442 to use CCF - Remove legacy samsung clock from mach-s3c24xx/ - Some of them are missed from previous pull-request - Clock related sutff got ack from Mike and Tomasz - Created the last commit due to missing changes during re-sorting because this branch is provided as a base to samsung clk tree. * tag 's3c24xx-clk' of http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: (23 commits) ARM: S3C24XX: fix merge conflict ARM: S3C24XX: remove SAMSUNG_CLOCK remnants after ccf conversion ARM: S3C24XX: remove legacy clock code ARM: S3C24XX: convert s3c2410 to common clock framework ARM: S3C24XX: convert s3c2440 and s3c2442 to common clock framework ARM: S3C24XX: add platform code for conversion to the common clock framework clk: samsung: add clock controller driver for s3c2410, s3c2440 and s3c2442 dt-bindings: add documentation for s3c2410 clock controller ARM: S3C24XX: enable usage of common dclk if common clock framework is enabled clk: samsung: add clock driver for external clock outputs ARM: S3C24XX: cpufreq-utils: don't write raw values to MPLLCON when using ccf ARM: S3C24XX: convert s3c2412 to common clock framework clk: samsung: add clock controller driver for s3c2412 dt-bindings: add documentation for s3c2412 clock controller clk: samsung: add plls used by the early s3c24xx cpus ARM: S3C24XX: only store clock registers when old clock code is active ARM: S3C24XX: Convert s3c2416 and s3c2443 to common clock framework ARM: dts: add clock data for s3c2416 ARM: S3C24XX: prevent conflicts between ccf and non-ccf s3c24xx-socs clk: samsung: add clock-driver for s3c2416, s3c2443 and s3c2450 ... Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
28d1079c9c
@ -0,0 +1,50 @@
|
||||
* Samsung S3C2410 Clock Controller
|
||||
|
||||
The S3C2410 clock controller generates and supplies clock to various controllers
|
||||
within the SoC. The clock binding described here is applicable to the s3c2410,
|
||||
s3c2440 and s3c2442 SoCs in the s3c24x family.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be one of the following.
|
||||
- "samsung,s3c2410-clock" - controller compatible with S3C2410 SoC.
|
||||
- "samsung,s3c2440-clock" - controller compatible with S3C2440 SoC.
|
||||
- "samsung,s3c2442-clock" - controller compatible with S3C2442 SoC.
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. Some of the clocks are available only
|
||||
on a particular SoC.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/samsung,s3c2410-clock.h header and can be used in device
|
||||
tree sources.
|
||||
|
||||
External clocks:
|
||||
|
||||
The xti clock used as input for the plls is generated outside the SoC. It is
|
||||
expected that is are defined using standard clock bindings with a
|
||||
clock-output-names value of "xti".
|
||||
|
||||
Example: Clock controller node:
|
||||
|
||||
clocks: clock-controller@4c000000 {
|
||||
compatible = "samsung,s3c2410-clock";
|
||||
reg = <0x4c000000 0x20>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes the clock generated by the clock
|
||||
controller (refer to the standard clock bindings for information about
|
||||
"clocks" and "clock-names" properties):
|
||||
|
||||
serial@50004000 {
|
||||
compatible = "samsung,s3c2440-uart";
|
||||
reg = <0x50004000 0x4000>;
|
||||
interrupts = <1 23 3 4>, <1 23 4 4>;
|
||||
clock-names = "uart", "clk_uart_baud2";
|
||||
clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>;
|
||||
status = "disabled";
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
* Samsung S3C2412 Clock Controller
|
||||
|
||||
The S3C2412 clock controller generates and supplies clock to various controllers
|
||||
within the SoC. The clock binding described here is applicable to the s3c2412
|
||||
and s3c2413 SoCs in the s3c24x family.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "samsung,s3c2412-clock"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. Some of the clocks are available only
|
||||
on a particular SoC.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/s3c2412.h header and can be used in device
|
||||
tree sources.
|
||||
|
||||
External clocks:
|
||||
|
||||
There are several clocks that are generated outside the SoC. It is expected
|
||||
that they are defined using standard clock bindings with following
|
||||
clock-output-names:
|
||||
- "xti" - crystal input - required,
|
||||
- "ext" - external clock source - optional,
|
||||
|
||||
Example: Clock controller node:
|
||||
|
||||
clocks: clock-controller@4c000000 {
|
||||
compatible = "samsung,s3c2412-clock";
|
||||
reg = <0x4c000000 0x20>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes the clock generated by the clock
|
||||
controller (refer to the standard clock bindings for information about
|
||||
"clocks" and "clock-names" properties):
|
||||
|
||||
serial@50004000 {
|
||||
compatible = "samsung,s3c2412-uart";
|
||||
reg = <0x50004000 0x4000>;
|
||||
interrupts = <1 23 3 4>, <1 23 4 4>;
|
||||
clock-names = "uart", "clk_uart_baud2", "clk_uart_baud3";
|
||||
clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
|
||||
<&clocks SCLK_UART>;
|
||||
status = "disabled";
|
||||
};
|
@ -0,0 +1,56 @@
|
||||
* Samsung S3C2443 Clock Controller
|
||||
|
||||
The S3C2443 clock controller generates and supplies clock to various controllers
|
||||
within the SoC. The clock binding described here is applicable to all SoCs in
|
||||
the s3c24x family starting with the s3c2443.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be one of the following.
|
||||
- "samsung,s3c2416-clock" - controller compatible with S3C2416 SoC.
|
||||
- "samsung,s3c2443-clock" - controller compatible with S3C2443 SoC.
|
||||
- "samsung,s3c2450-clock" - controller compatible with S3C2450 SoC.
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. Some of the clocks are available only
|
||||
on a particular SoC.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
dt-bindings/clock/s3c2443.h header and can be used in device
|
||||
tree sources.
|
||||
|
||||
External clocks:
|
||||
|
||||
There are several clocks that are generated outside the SoC. It is expected
|
||||
that they are defined using standard clock bindings with following
|
||||
clock-output-names:
|
||||
- "xti" - crystal input - required,
|
||||
- "ext" - external clock source - optional,
|
||||
- "ext_i2s" - external I2S clock - optional,
|
||||
- "ext_uart" - external uart clock - optional,
|
||||
|
||||
Example: Clock controller node:
|
||||
|
||||
clocks: clock-controller@4c000000 {
|
||||
compatible = "samsung,s3c2416-clock";
|
||||
reg = <0x4c000000 0x40>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes the clock generated by the clock
|
||||
controller (refer to the standard clock bindings for information about
|
||||
"clocks" and "clock-names" properties):
|
||||
|
||||
serial@50004000 {
|
||||
compatible = "samsung,s3c2440-uart";
|
||||
reg = <0x50004000 0x4000>;
|
||||
interrupts = <1 23 3 4>, <1 23 4 4>;
|
||||
clock-names = "uart", "clk_uart_baud2",
|
||||
"clk_uart_baud3";
|
||||
clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
|
||||
<&clocks SCLK_UART>;
|
||||
status = "disabled";
|
||||
};
|
@ -19,6 +19,19 @@
|
||||
reg = <0x30000000 0x4000000>;
|
||||
};
|
||||
|
||||
clocks {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
xti: xti {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <12000000>;
|
||||
clock-output-names = "xti";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
serial@50000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
|
@ -8,6 +8,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/s3c2443.h>
|
||||
#include "s3c24xx.dtsi"
|
||||
#include "s3c2416-pinctrl.dtsi"
|
||||
|
||||
@ -28,26 +29,53 @@
|
||||
compatible = "samsung,s3c2416-irq";
|
||||
};
|
||||
|
||||
clocks: clock-controller@0x4c000000 {
|
||||
compatible = "samsung,s3c2416-clock";
|
||||
reg = <0x4c000000 0x40>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
pinctrl@56000000 {
|
||||
compatible = "samsung,s3c2416-pinctrl";
|
||||
};
|
||||
|
||||
timer@51000000 {
|
||||
clocks = <&clocks PCLK_PWM>;
|
||||
clock-names = "timers";
|
||||
};
|
||||
|
||||
serial@50000000 {
|
||||
compatible = "samsung,s3c2440-uart";
|
||||
clock-names = "uart", "clk_uart_baud2",
|
||||
"clk_uart_baud3";
|
||||
clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
|
||||
<&clocks SCLK_UART>;
|
||||
};
|
||||
|
||||
serial@50004000 {
|
||||
compatible = "samsung,s3c2440-uart";
|
||||
clock-names = "uart", "clk_uart_baud2",
|
||||
"clk_uart_baud3";
|
||||
clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
|
||||
<&clocks SCLK_UART>;
|
||||
};
|
||||
|
||||
serial@50008000 {
|
||||
compatible = "samsung,s3c2440-uart";
|
||||
clock-names = "uart", "clk_uart_baud2",
|
||||
"clk_uart_baud3";
|
||||
clocks = <&clocks PCLK_UART2>, <&clocks PCLK_UART2>,
|
||||
<&clocks SCLK_UART>;
|
||||
};
|
||||
|
||||
serial@5000C000 {
|
||||
compatible = "samsung,s3c2440-uart";
|
||||
reg = <0x5000C000 0x4000>;
|
||||
interrupts = <1 18 24 4>, <1 18 25 4>;
|
||||
clock-names = "uart", "clk_uart_baud2",
|
||||
"clk_uart_baud3";
|
||||
clocks = <&clocks PCLK_UART3>, <&clocks PCLK_UART3>,
|
||||
<&clocks SCLK_UART>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@ -55,6 +83,10 @@
|
||||
compatible = "samsung,s3c6410-sdhci";
|
||||
reg = <0x4AC00000 0x100>;
|
||||
interrupts = <0 0 21 3>;
|
||||
clock-names = "hsmmc", "mmc_busclk.0",
|
||||
"mmc_busclk.2";
|
||||
clocks = <&clocks HCLK_HSMMC0>, <&clocks HCLK_HSMMC0>,
|
||||
<&clocks MUX_HSMMC0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@ -62,18 +94,28 @@
|
||||
compatible = "samsung,s3c6410-sdhci";
|
||||
reg = <0x4A800000 0x100>;
|
||||
interrupts = <0 0 20 3>;
|
||||
clock-names = "hsmmc", "mmc_busclk.0",
|
||||
"mmc_busclk.2";
|
||||
clocks = <&clocks HCLK_HSMMC1>, <&clocks HCLK_HSMMC1>,
|
||||
<&clocks MUX_HSMMC1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
watchdog@53000000 {
|
||||
interrupts = <1 9 27 3>;
|
||||
clocks = <&clocks PCLK_WDT>;
|
||||
clock-names = "watchdog";
|
||||
};
|
||||
|
||||
rtc@57000000 {
|
||||
compatible = "samsung,s3c2416-rtc";
|
||||
clocks = <&clocks PCLK_RTC>;
|
||||
clock-names = "rtc";
|
||||
};
|
||||
|
||||
i2c@54000000 {
|
||||
compatible = "samsung,s3c2440-i2c";
|
||||
clocks = <&clocks PCLK_I2C0>;
|
||||
clock-names = "i2c";
|
||||
};
|
||||
};
|
||||
|
@ -18,6 +18,18 @@ config PLAT_S3C24XX
|
||||
help
|
||||
Base platform code for any Samsung S3C24XX device
|
||||
|
||||
config S3C2410_COMMON_CLK
|
||||
bool
|
||||
help
|
||||
Build the s3c2410 clock driver based on the common clock framework.
|
||||
|
||||
config S3C2410_COMMON_DCLK
|
||||
bool
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Temporary symbol to build the dclk driver based on the common clock
|
||||
framework.
|
||||
|
||||
menu "SAMSUNG S3C24XX SoCs Support"
|
||||
|
||||
comment "S3C24XX SoCs"
|
||||
@ -25,9 +37,10 @@ comment "S3C24XX SoCs"
|
||||
config CPU_S3C2410
|
||||
bool "SAMSUNG S3C2410"
|
||||
default y
|
||||
select COMMON_CLK
|
||||
select CPU_ARM920T
|
||||
select CPU_LLSERIAL_S3C2410
|
||||
select S3C2410_CLOCK
|
||||
select S3C2410_COMMON_CLK
|
||||
select S3C2410_DMA if S3C24XX_DMA
|
||||
select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ
|
||||
select S3C2410_PM if PM
|
||||
@ -38,8 +51,10 @@ config CPU_S3C2410
|
||||
|
||||
config CPU_S3C2412
|
||||
bool "SAMSUNG S3C2412"
|
||||
select COMMON_CLK
|
||||
select CPU_ARM926T
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select S3C2412_COMMON_CLK
|
||||
select S3C2412_DMA if S3C24XX_DMA
|
||||
select S3C2412_PM if PM
|
||||
help
|
||||
@ -47,20 +62,21 @@ config CPU_S3C2412
|
||||
|
||||
config CPU_S3C2416
|
||||
bool "SAMSUNG S3C2416/S3C2450"
|
||||
select COMMON_CLK
|
||||
select CPU_ARM926T
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select S3C2416_PM if PM
|
||||
select S3C2443_COMMON
|
||||
select S3C2443_COMMON_CLK
|
||||
select S3C2443_DMA if S3C24XX_DMA
|
||||
select SAMSUNG_CLKSRC
|
||||
help
|
||||
Support for the S3C2416 SoC from the S3C24XX line
|
||||
|
||||
config CPU_S3C2440
|
||||
bool "SAMSUNG S3C2440"
|
||||
select COMMON_CLK
|
||||
select CPU_ARM920T
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select S3C2410_CLOCK
|
||||
select S3C2410_COMMON_CLK
|
||||
select S3C2410_PM if PM
|
||||
select S3C2440_DMA if S3C24XX_DMA
|
||||
help
|
||||
@ -68,9 +84,10 @@ config CPU_S3C2440
|
||||
|
||||
config CPU_S3C2442
|
||||
bool "SAMSUNG S3C2442"
|
||||
select COMMON_CLK
|
||||
select CPU_ARM920T
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select S3C2410_CLOCK
|
||||
select S3C2410_COMMON_CLK
|
||||
select S3C2410_DMA if S3C24XX_DMA
|
||||
select S3C2410_PM if PM
|
||||
help
|
||||
@ -83,27 +100,16 @@ config CPU_S3C244X
|
||||
|
||||
config CPU_S3C2443
|
||||
bool "SAMSUNG S3C2443"
|
||||
select COMMON_CLK
|
||||
select CPU_ARM920T
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select S3C2443_COMMON
|
||||
select S3C2443_COMMON_CLK
|
||||
select S3C2443_DMA if S3C24XX_DMA
|
||||
select SAMSUNG_CLKSRC
|
||||
help
|
||||
Support for the S3C2443 SoC from the S3C24XX line
|
||||
|
||||
# common code
|
||||
|
||||
config S3C2410_CLOCK
|
||||
bool
|
||||
help
|
||||
Clock code for the S3C2410, and similar processors which
|
||||
is currently includes the S3C2410, S3C2440, S3C2442.
|
||||
|
||||
config S3C24XX_DCLK
|
||||
bool
|
||||
help
|
||||
Clock code for supporting DCLK/CLKOUT on S3C24XX architectures
|
||||
|
||||
config S3C24XX_SMDK
|
||||
bool
|
||||
help
|
||||
@ -258,8 +264,8 @@ config ARCH_BAST
|
||||
bool "Simtec Electronics BAST (EB2410ITX)"
|
||||
select ISA
|
||||
select MACH_BAST_IDE
|
||||
select S3C2410_COMMON_DCLK if COMMON_CLK
|
||||
select S3C2410_IOTIMING if ARM_S3C2410_CPUFREQ
|
||||
select S3C24XX_DCLK
|
||||
select S3C24XX_SIMTEC_NOR
|
||||
select S3C24XX_SIMTEC_PM if PM
|
||||
select S3C24XX_SIMTEC_USB
|
||||
@ -340,7 +346,7 @@ config MACH_TCT_HAMMER
|
||||
config MACH_VR1000
|
||||
bool "Thorcom VR1000"
|
||||
select MACH_BAST_IDE
|
||||
select S3C24XX_DCLK
|
||||
select S3C2410_COMMON_DCLK if COMMON_CLK
|
||||
select S3C24XX_SIMTEC_NOR
|
||||
select S3C24XX_SIMTEC_PM if PM
|
||||
select S3C24XX_SIMTEC_USB
|
||||
@ -359,6 +365,11 @@ config S3C2412_PM_SLEEP
|
||||
|
||||
if CPU_S3C2412
|
||||
|
||||
config S3C2412_COMMON_CLK
|
||||
bool
|
||||
help
|
||||
Build the s3c2412 clock driver based on the common clock framework.
|
||||
|
||||
config CPU_S3C2412_ONLY
|
||||
bool
|
||||
depends on !CPU_S3C2410 && !CPU_S3C2416 && !CPU_S3C2440 && \
|
||||
@ -519,8 +530,8 @@ comment "S3C2440 Boards"
|
||||
config MACH_ANUBIS
|
||||
bool "Simtec Electronics ANUBIS"
|
||||
select HAVE_PATA_PLATFORM
|
||||
select S3C2410_COMMON_DCLK if COMMON_CLK
|
||||
select S3C2440_XTAL_12000000
|
||||
select S3C24XX_DCLK
|
||||
select S3C24XX_SIMTEC_PM if PM
|
||||
select S3C_DEV_USB_HOST
|
||||
help
|
||||
@ -558,9 +569,9 @@ config MACH_NEXCODER_2440
|
||||
|
||||
config MACH_OSIRIS
|
||||
bool "Simtec IM2440D20 (OSIRIS) module"
|
||||
select S3C2410_COMMON_DCLK if COMMON_CLK
|
||||
select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ
|
||||
select S3C2440_XTAL_12000000
|
||||
select S3C24XX_DCLK
|
||||
select S3C24XX_SIMTEC_PM if PM
|
||||
select S3C_DEV_NAND
|
||||
select S3C_DEV_USB_HOST
|
||||
@ -629,9 +640,9 @@ config MACH_RX1950
|
||||
bool "HP iPAQ rx1950"
|
||||
select I2C
|
||||
select PM_H1940 if PM
|
||||
select S3C2410_COMMON_DCLK if COMMON_CLK
|
||||
select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ
|
||||
select S3C2440_XTAL_16934400
|
||||
select S3C24XX_DCLK
|
||||
select S3C24XX_PWM
|
||||
select S3C_DEV_NAND
|
||||
help
|
||||
@ -641,11 +652,11 @@ endif # CPU_S3C2442
|
||||
|
||||
if CPU_S3C2443 || CPU_S3C2416
|
||||
|
||||
config S3C2443_COMMON
|
||||
config S3C2443_COMMON_CLK
|
||||
bool
|
||||
help
|
||||
Common code for the S3C2443 and similar processors, which includes
|
||||
the S3C2416 and S3C2450.
|
||||
Temporary symbol to build the clock driver based on the common clock
|
||||
framework.
|
||||
|
||||
config S3C2443_DMA
|
||||
bool
|
||||
|
@ -21,22 +21,22 @@ obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o
|
||||
obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o
|
||||
obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o
|
||||
|
||||
obj-$(CONFIG_CPU_S3C2412) += s3c2412.o clock-s3c2412.o
|
||||
obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
|
||||
obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o
|
||||
obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o
|
||||
obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o
|
||||
|
||||
obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock-s3c2416.o
|
||||
obj-$(CONFIG_CPU_S3C2416) += s3c2416.o
|
||||
obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o
|
||||
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o clock-s3c2440.o
|
||||
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o
|
||||
obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
|
||||
obj-$(CONFIG_CPU_S3C244X) += s3c244x.o clock-s3c244x.o
|
||||
obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
|
||||
obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o
|
||||
obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o
|
||||
obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o
|
||||
|
||||
obj-$(CONFIG_CPU_S3C2443) += s3c2443.o clock-s3c2443.o
|
||||
obj-$(CONFIG_CPU_S3C2443) += s3c2443.o
|
||||
|
||||
# PM
|
||||
|
||||
@ -44,16 +44,13 @@ obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o
|
||||
|
||||
# common code
|
||||
|
||||
obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o
|
||||
obj-$(CONFIG_S3C24XX_DMA) += dma.o
|
||||
|
||||
obj-$(CONFIG_S3C2410_CLOCK) += clock-s3c2410.o
|
||||
obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o
|
||||
|
||||
obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o
|
||||
obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o
|
||||
|
||||
obj-$(CONFIG_S3C2443_COMMON) += common-s3c2443.o
|
||||
obj-$(CONFIG_S3C2443_DMA) += dma-s3c2443.o
|
||||
|
||||
#
|
||||
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2008 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
* http://armlinux.simtec.co.uk/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* S3C24XX - definitions for DCLK and CLKOUT registers
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
/* clocks that could be registered by external code */
|
||||
|
||||
static int s3c24xx_dclk_enable(struct clk *clk, int enable)
|
||||
{
|
||||
unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
|
||||
|
||||
if (enable)
|
||||
dclkcon |= clk->ctrlbit;
|
||||
else
|
||||
dclkcon &= ~clk->ctrlbit;
|
||||
|
||||
__raw_writel(dclkcon, S3C24XX_DCLKCON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long dclkcon;
|
||||
unsigned int uclk;
|
||||
|
||||
if (parent == &clk_upll)
|
||||
uclk = 1;
|
||||
else if (parent == &clk_p)
|
||||
uclk = 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
dclkcon = __raw_readl(S3C24XX_DCLKCON);
|
||||
|
||||
if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
|
||||
if (uclk)
|
||||
dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
|
||||
else
|
||||
dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
|
||||
} else {
|
||||
if (uclk)
|
||||
dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
|
||||
else
|
||||
dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
|
||||
}
|
||||
|
||||
__raw_writel(dclkcon, S3C24XX_DCLKCON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long div;
|
||||
|
||||
if ((rate == 0) || !clk->parent)
|
||||
return 0;
|
||||
|
||||
div = clk_get_rate(clk->parent) / rate;
|
||||
if (div < 2)
|
||||
div = 2;
|
||||
else if (div > 16)
|
||||
div = 16;
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
static unsigned long s3c24xx_round_dclk_rate(struct clk *clk,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long div = s3c24xx_calc_div(clk, rate);
|
||||
|
||||
if (div == 0)
|
||||
return 0;
|
||||
|
||||
return clk_get_rate(clk->parent) / div;
|
||||
}
|
||||
|
||||
static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long mask, data, div = s3c24xx_calc_div(clk, rate);
|
||||
|
||||
if (div == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (clk == &s3c24xx_dclk0) {
|
||||
mask = S3C2410_DCLKCON_DCLK0_DIV_MASK |
|
||||
S3C2410_DCLKCON_DCLK0_CMP_MASK;
|
||||
data = S3C2410_DCLKCON_DCLK0_DIV(div) |
|
||||
S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2);
|
||||
} else if (clk == &s3c24xx_dclk1) {
|
||||
mask = S3C2410_DCLKCON_DCLK1_DIV_MASK |
|
||||
S3C2410_DCLKCON_DCLK1_CMP_MASK;
|
||||
data = S3C2410_DCLKCON_DCLK1_DIV(div) |
|
||||
S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2);
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
clk->rate = clk_get_rate(clk->parent) / div;
|
||||
__raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data),
|
||||
S3C24XX_DCLKCON);
|
||||
return clk->rate;
|
||||
}
|
||||
static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long mask;
|
||||
unsigned long source;
|
||||
|
||||
/* calculate the MISCCR setting for the clock */
|
||||
|
||||
if (parent == &clk_mpll)
|
||||
source = S3C2410_MISCCR_CLK0_MPLL;
|
||||
else if (parent == &clk_upll)
|
||||
source = S3C2410_MISCCR_CLK0_UPLL;
|
||||
else if (parent == &clk_f)
|
||||
source = S3C2410_MISCCR_CLK0_FCLK;
|
||||
else if (parent == &clk_h)
|
||||
source = S3C2410_MISCCR_CLK0_HCLK;
|
||||
else if (parent == &clk_p)
|
||||
source = S3C2410_MISCCR_CLK0_PCLK;
|
||||
else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
|
||||
source = S3C2410_MISCCR_CLK0_DCLK0;
|
||||
else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
|
||||
source = S3C2410_MISCCR_CLK0_DCLK0;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
if (clk == &s3c24xx_clkout0)
|
||||
mask = S3C2410_MISCCR_CLK0_MASK;
|
||||
else {
|
||||
source <<= 4;
|
||||
mask = S3C2410_MISCCR_CLK1_MASK;
|
||||
}
|
||||
|
||||
s3c2410_modify_misccr(mask, source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* external clock definitions */
|
||||
|
||||
static struct clk_ops dclk_ops = {
|
||||
.set_parent = s3c24xx_dclk_setparent,
|
||||
.set_rate = s3c24xx_set_dclk_rate,
|
||||
.round_rate = s3c24xx_round_dclk_rate,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_dclk0 = {
|
||||
.name = "dclk0",
|
||||
.ctrlbit = S3C2410_DCLKCON_DCLK0EN,
|
||||
.enable = s3c24xx_dclk_enable,
|
||||
.ops = &dclk_ops,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_dclk1 = {
|
||||
.name = "dclk1",
|
||||
.ctrlbit = S3C2410_DCLKCON_DCLK1EN,
|
||||
.enable = s3c24xx_dclk_enable,
|
||||
.ops = &dclk_ops,
|
||||
};
|
||||
|
||||
static struct clk_ops clkout_ops = {
|
||||
.set_parent = s3c24xx_clkout_setparent,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_clkout0 = {
|
||||
.name = "clkout0",
|
||||
.ops = &clkout_ops,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_clkout1 = {
|
||||
.name = "clkout1",
|
||||
.ops = &clkout_ops,
|
||||
};
|
@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2410,S3C2440,S3C2442 Clock control support
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
int s3c2410_clkcon_enable(struct clk *clk, int enable)
|
||||
{
|
||||
unsigned int clocks = clk->ctrlbit;
|
||||
unsigned long clkcon;
|
||||
|
||||
clkcon = __raw_readl(S3C2410_CLKCON);
|
||||
|
||||
if (enable)
|
||||
clkcon |= clocks;
|
||||
else
|
||||
clkcon &= ~clocks;
|
||||
|
||||
/* ensure none of the special function bits set */
|
||||
clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
|
||||
|
||||
__raw_writel(clkcon, S3C2410_CLKCON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2410_upll_enable(struct clk *clk, int enable)
|
||||
{
|
||||
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
|
||||
unsigned long orig = clkslow;
|
||||
|
||||
if (enable)
|
||||
clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
|
||||
else
|
||||
clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
|
||||
|
||||
__raw_writel(clkslow, S3C2410_CLKSLOW);
|
||||
|
||||
/* if we started the UPLL, then allow to settle */
|
||||
|
||||
if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
|
||||
udelay(200);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* standard clock definitions */
|
||||
|
||||
static struct clk init_clocks_off[] = {
|
||||
{
|
||||
.name = "nand",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_NAND,
|
||||
}, {
|
||||
.name = "sdi",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_SDI,
|
||||
}, {
|
||||
.name = "adc",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_ADC,
|
||||
}, {
|
||||
.name = "i2c",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_IIC,
|
||||
}, {
|
||||
.name = "iis",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_IIS,
|
||||
}, {
|
||||
.name = "spi",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_SPI,
|
||||
}
|
||||
};
|
||||
|
||||
static struct clk clk_lcd = {
|
||||
.name = "lcd",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_LCDC,
|
||||
};
|
||||
|
||||
static struct clk clk_gpio = {
|
||||
.name = "gpio",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_GPIO,
|
||||
};
|
||||
|
||||
static struct clk clk_usb_host = {
|
||||
.name = "usb-host",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_USBH,
|
||||
};
|
||||
|
||||
static struct clk clk_usb_device = {
|
||||
.name = "usb-device",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_USBD,
|
||||
};
|
||||
|
||||
static struct clk clk_timers = {
|
||||
.name = "timers",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_PWMT,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_clk_uart0 = {
|
||||
.name = "uart",
|
||||
.devname = "s3c2410-uart.0",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_UART0,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_clk_uart1 = {
|
||||
.name = "uart",
|
||||
.devname = "s3c2410-uart.1",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_UART1,
|
||||
};
|
||||
|
||||
struct clk s3c24xx_clk_uart2 = {
|
||||
.name = "uart",
|
||||
.devname = "s3c2410-uart.2",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_UART2,
|
||||
};
|
||||
|
||||
static struct clk clk_rtc = {
|
||||
.name = "rtc",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2410_CLKCON_RTC,
|
||||
};
|
||||
|
||||
static struct clk clk_watchdog = {
|
||||
.name = "watchdog",
|
||||
.parent = &clk_p,
|
||||
.ctrlbit = 0,
|
||||
};
|
||||
|
||||
static struct clk clk_usb_bus_host = {
|
||||
.name = "usb-bus-host",
|
||||
.parent = &clk_usb_bus,
|
||||
};
|
||||
|
||||
static struct clk clk_usb_bus_gadget = {
|
||||
.name = "usb-bus-gadget",
|
||||
.parent = &clk_usb_bus,
|
||||
};
|
||||
|
||||
static struct clk *init_clocks[] = {
|
||||
&clk_lcd,
|
||||
&clk_gpio,
|
||||
&clk_usb_host,
|
||||
&clk_usb_device,
|
||||
&clk_timers,
|
||||
&s3c24xx_clk_uart0,
|
||||
&s3c24xx_clk_uart1,
|
||||
&s3c24xx_clk_uart2,
|
||||
&clk_rtc,
|
||||
&clk_watchdog,
|
||||
&clk_usb_bus_host,
|
||||
&clk_usb_bus_gadget,
|
||||
};
|
||||
|
||||
/* s3c2410_baseclk_add()
|
||||
*
|
||||
* Add all the clocks used by the s3c2410 or compatible CPUs
|
||||
* such as the S3C2440 and S3C2442.
|
||||
*
|
||||
* We cannot use a system device as we are needed before any
|
||||
* of the init-calls that initialise the devices are actually
|
||||
* done.
|
||||
*/
|
||||
|
||||
int __init s3c2410_baseclk_add(void)
|
||||
{
|
||||
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
|
||||
unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
|
||||
struct clk *xtal;
|
||||
int ret;
|
||||
int ptr;
|
||||
|
||||
clk_upll.enable = s3c2410_upll_enable;
|
||||
|
||||
if (s3c24xx_register_clock(&clk_usb_bus) < 0)
|
||||
printk(KERN_ERR "failed to register usb bus clock\n");
|
||||
|
||||
/* register clocks from clock array */
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++) {
|
||||
struct clk *clkp = init_clocks[ptr];
|
||||
|
||||
/* ensure that we note the clock state */
|
||||
|
||||
clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
|
||||
|
||||
ret = s3c24xx_register_clock(clkp);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register clock %s (%d)\n",
|
||||
clkp->name, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* We must be careful disabling the clocks we are not intending to
|
||||
* be using at boot time, as subsystems such as the LCD which do
|
||||
* their own DMA requests to the bus can cause the system to lockup
|
||||
* if they where in the middle of requesting bus access.
|
||||
*
|
||||
* Disabling the LCD clock if the LCD is active is very dangerous,
|
||||
* and therefore the bootloader should be careful to not enable
|
||||
* the LCD clock if it is not needed.
|
||||
*/
|
||||
|
||||
/* install (and disable) the clocks we do not need immediately */
|
||||
|
||||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
|
||||
/* show the clock-slow value */
|
||||
|
||||
xtal = clk_get(NULL, "xtal");
|
||||
|
||||
printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
|
||||
print_mhz(clk_get_rate(xtal) /
|
||||
( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
|
||||
(clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
|
||||
(clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
|
||||
(clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,760 +0,0 @@
|
||||
/* linux/arch/arm/mach-s3c2412/clock.c
|
||||
*
|
||||
* Copyright (c) 2006 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2412,S3C2413 Clock control support
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
/* We currently have to assume that the system is running
|
||||
* from the XTPll input, and that all ***REFCLKs are being
|
||||
* fed from it, as we cannot read the state of OM[4] from
|
||||
* software.
|
||||
*
|
||||
* It would be possible for each board initialisation to
|
||||
* set the correct muxing at initialisation
|
||||
*/
|
||||
|
||||
static int s3c2412_clkcon_enable(struct clk *clk, int enable)
|
||||
{
|
||||
unsigned int clocks = clk->ctrlbit;
|
||||
unsigned long clkcon;
|
||||
|
||||
clkcon = __raw_readl(S3C2410_CLKCON);
|
||||
|
||||
if (enable)
|
||||
clkcon |= clocks;
|
||||
else
|
||||
clkcon &= ~clocks;
|
||||
|
||||
__raw_writel(clkcon, S3C2410_CLKCON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2412_upll_enable(struct clk *clk, int enable)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
unsigned long orig = upllcon;
|
||||
|
||||
if (!enable)
|
||||
upllcon |= S3C2412_PLLCON_OFF;
|
||||
else
|
||||
upllcon &= ~S3C2412_PLLCON_OFF;
|
||||
|
||||
__raw_writel(upllcon, S3C2410_UPLLCON);
|
||||
|
||||
/* allow ~150uS for the PLL to settle and lock */
|
||||
|
||||
if (enable && (orig & S3C2412_PLLCON_OFF))
|
||||
udelay(150);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clock selections */
|
||||
|
||||
static struct clk clk_erefclk = {
|
||||
.name = "erefclk",
|
||||
};
|
||||
|
||||
static struct clk clk_urefclk = {
|
||||
.name = "urefclk",
|
||||
};
|
||||
|
||||
static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
|
||||
if (parent == &clk_urefclk)
|
||||
clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
|
||||
else if (parent == &clk_upll)
|
||||
clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
__raw_writel(clksrc, S3C2412_CLKSRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_usysclk = {
|
||||
.name = "usysclk",
|
||||
.parent = &clk_xtal,
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_parent = s3c2412_setparent_usysclk,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk clk_mrefclk = {
|
||||
.name = "mrefclk",
|
||||
.parent = &clk_xtal,
|
||||
};
|
||||
|
||||
static struct clk clk_mdivclk = {
|
||||
.name = "mdivclk",
|
||||
.parent = &clk_xtal,
|
||||
};
|
||||
|
||||
static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
|
||||
if (parent == &clk_usysclk)
|
||||
clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
|
||||
else if (parent == &clk_h)
|
||||
clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
__raw_writel(clksrc, S3C2412_CLKSRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
int div;
|
||||
|
||||
if (rate > parent_rate)
|
||||
return parent_rate;
|
||||
|
||||
div = parent_rate / rate;
|
||||
if (div > 2)
|
||||
div = 2;
|
||||
|
||||
return parent_rate / div;
|
||||
}
|
||||
|
||||
static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
|
||||
}
|
||||
|
||||
static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
rate = s3c2412_roundrate_usbsrc(clk, rate);
|
||||
|
||||
if ((parent_rate / rate) == 2)
|
||||
clkdivn |= S3C2412_CLKDIVN_USB48DIV;
|
||||
else
|
||||
clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
|
||||
|
||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_usbsrc = {
|
||||
.name = "usbsrc",
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2412_getrate_usbsrc,
|
||||
.set_rate = s3c2412_setrate_usbsrc,
|
||||
.round_rate = s3c2412_roundrate_usbsrc,
|
||||
.set_parent = s3c2412_setparent_usbsrc,
|
||||
},
|
||||
};
|
||||
|
||||
static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
|
||||
if (parent == &clk_mdivclk)
|
||||
clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
|
||||
else if (parent == &clk_mpll)
|
||||
clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
__raw_writel(clksrc, S3C2412_CLKSRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_msysclk = {
|
||||
.name = "msysclk",
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_parent = s3c2412_setparent_msysclk,
|
||||
},
|
||||
};
|
||||
|
||||
static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long clkdiv;
|
||||
unsigned long dvs;
|
||||
|
||||
/* Note, we current equate fclk andf msysclk for S3C2412 */
|
||||
|
||||
if (parent == &clk_msysclk || parent == &clk_f)
|
||||
dvs = 0;
|
||||
else if (parent == &clk_h)
|
||||
dvs = S3C2412_CLKDIVN_DVSEN;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
/* update this under irq lockdown, clkdivn is not protected
|
||||
* by the clock system. */
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
clkdiv = __raw_readl(S3C2410_CLKDIVN);
|
||||
clkdiv &= ~S3C2412_CLKDIVN_DVSEN;
|
||||
clkdiv |= dvs;
|
||||
__raw_writel(clkdiv, S3C2410_CLKDIVN);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_armclk = {
|
||||
.name = "armclk",
|
||||
.parent = &clk_msysclk,
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_parent = s3c2412_setparent_armclk,
|
||||
},
|
||||
};
|
||||
|
||||
/* these next clocks have an divider immediately after them,
|
||||
* so we can register them with their divider and leave out the
|
||||
* intermediate clock stage
|
||||
*/
|
||||
static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
int div;
|
||||
|
||||
if (rate > parent_rate)
|
||||
return parent_rate;
|
||||
|
||||
/* note, we remove the +/- 1 calculations as they cancel out */
|
||||
|
||||
div = (rate / parent_rate);
|
||||
|
||||
if (div < 1)
|
||||
div = 1;
|
||||
else if (div > 16)
|
||||
div = 16;
|
||||
|
||||
return parent_rate / div;
|
||||
}
|
||||
|
||||
static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
|
||||
if (parent == &clk_erefclk)
|
||||
clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
|
||||
else if (parent == &clk_mpll)
|
||||
clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
__raw_writel(clksrc, S3C2412_CLKSRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long s3c2412_getrate_uart(struct clk *clk)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
div &= S3C2412_CLKDIVN_UARTDIV_MASK;
|
||||
div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
rate = s3c2412_roundrate_clksrc(clk, rate);
|
||||
|
||||
clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
|
||||
clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
|
||||
|
||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_uart = {
|
||||
.name = "uartclk",
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2412_getrate_uart,
|
||||
.set_rate = s3c2412_setrate_uart,
|
||||
.set_parent = s3c2412_setparent_uart,
|
||||
.round_rate = s3c2412_roundrate_clksrc,
|
||||
},
|
||||
};
|
||||
|
||||
static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
|
||||
if (parent == &clk_erefclk)
|
||||
clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
|
||||
else if (parent == &clk_mpll)
|
||||
clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
__raw_writel(clksrc, S3C2412_CLKSRC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long s3c2412_getrate_i2s(struct clk *clk)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
div &= S3C2412_CLKDIVN_I2SDIV_MASK;
|
||||
div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
rate = s3c2412_roundrate_clksrc(clk, rate);
|
||||
|
||||
clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
|
||||
clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
|
||||
|
||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_i2s = {
|
||||
.name = "i2sclk",
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2412_getrate_i2s,
|
||||
.set_rate = s3c2412_setrate_i2s,
|
||||
.set_parent = s3c2412_setparent_i2s,
|
||||
.round_rate = s3c2412_roundrate_clksrc,
|
||||
},
|
||||
};
|
||||
|
||||
static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
|
||||
if (parent == &clk_usysclk)
|
||||
clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
|
||||
else if (parent == &clk_h)
|
||||
clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
__raw_writel(clksrc, S3C2412_CLKSRC);
|
||||
return 0;
|
||||
}
|
||||
static unsigned long s3c2412_getrate_cam(struct clk *clk)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
div &= S3C2412_CLKDIVN_CAMDIV_MASK;
|
||||
div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
rate = s3c2412_roundrate_clksrc(clk, rate);
|
||||
|
||||
clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
|
||||
clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
|
||||
|
||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_cam = {
|
||||
.name = "camif-upll", /* same as 2440 name */
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2412_getrate_cam,
|
||||
.set_rate = s3c2412_setrate_cam,
|
||||
.set_parent = s3c2412_setparent_cam,
|
||||
.round_rate = s3c2412_roundrate_clksrc,
|
||||
},
|
||||
};
|
||||
|
||||
/* standard clock definitions */
|
||||
|
||||
static struct clk init_clocks_disable[] = {
|
||||
{
|
||||
.name = "nand",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_NAND,
|
||||
}, {
|
||||
.name = "sdi",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_SDI,
|
||||
}, {
|
||||
.name = "adc",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_ADC,
|
||||
}, {
|
||||
.name = "i2c",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_IIC,
|
||||
}, {
|
||||
.name = "iis",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_IIS,
|
||||
}, {
|
||||
.name = "spi",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_SPI,
|
||||
}
|
||||
};
|
||||
|
||||
static struct clk init_clocks[] = {
|
||||
{
|
||||
.name = "dma.0",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_DMA0,
|
||||
}, {
|
||||
.name = "dma.1",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_DMA1,
|
||||
}, {
|
||||
.name = "dma.2",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_DMA2,
|
||||
}, {
|
||||
.name = "dma.3",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_DMA3,
|
||||
}, {
|
||||
.name = "lcd",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_LCDC,
|
||||
}, {
|
||||
.name = "gpio",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_GPIO,
|
||||
}, {
|
||||
.name = "usb-host",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_USBH,
|
||||
}, {
|
||||
.name = "usb-device",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_USBD,
|
||||
}, {
|
||||
.name = "timers",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_PWMT,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2412-uart.0",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_UART0,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2412-uart.1",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_UART1,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2412-uart.2",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_UART2,
|
||||
}, {
|
||||
.name = "rtc",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_RTC,
|
||||
}, {
|
||||
.name = "watchdog",
|
||||
.parent = &clk_p,
|
||||
.ctrlbit = 0,
|
||||
}, {
|
||||
.name = "usb-bus-gadget",
|
||||
.parent = &clk_usb_bus,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_USB_DEV48,
|
||||
}, {
|
||||
.name = "usb-bus-host",
|
||||
.parent = &clk_usb_bus,
|
||||
.enable = s3c2412_clkcon_enable,
|
||||
.ctrlbit = S3C2412_CLKCON_USB_HOST48,
|
||||
}
|
||||
};
|
||||
|
||||
/* clocks to add where we need to check their parentage */
|
||||
|
||||
struct clk_init {
|
||||
struct clk *clk;
|
||||
unsigned int bit;
|
||||
struct clk *src_0;
|
||||
struct clk *src_1;
|
||||
};
|
||||
|
||||
static struct clk_init clks_src[] __initdata = {
|
||||
{
|
||||
.clk = &clk_usysclk,
|
||||
.bit = S3C2412_CLKSRC_USBCLK_HCLK,
|
||||
.src_0 = &clk_urefclk,
|
||||
.src_1 = &clk_upll,
|
||||
}, {
|
||||
.clk = &clk_i2s,
|
||||
.bit = S3C2412_CLKSRC_I2SCLK_MPLL,
|
||||
.src_0 = &clk_erefclk,
|
||||
.src_1 = &clk_mpll,
|
||||
}, {
|
||||
.clk = &clk_cam,
|
||||
.bit = S3C2412_CLKSRC_CAMCLK_HCLK,
|
||||
.src_0 = &clk_usysclk,
|
||||
.src_1 = &clk_h,
|
||||
}, {
|
||||
.clk = &clk_msysclk,
|
||||
.bit = S3C2412_CLKSRC_MSYSCLK_MPLL,
|
||||
.src_0 = &clk_mdivclk,
|
||||
.src_1 = &clk_mpll,
|
||||
}, {
|
||||
.clk = &clk_uart,
|
||||
.bit = S3C2412_CLKSRC_UARTCLK_MPLL,
|
||||
.src_0 = &clk_erefclk,
|
||||
.src_1 = &clk_mpll,
|
||||
}, {
|
||||
.clk = &clk_usbsrc,
|
||||
.bit = S3C2412_CLKSRC_USBCLK_HCLK,
|
||||
.src_0 = &clk_usysclk,
|
||||
.src_1 = &clk_h,
|
||||
/* here we assume OM[4] select xtal */
|
||||
}, {
|
||||
.clk = &clk_erefclk,
|
||||
.bit = S3C2412_CLKSRC_EREFCLK_EXTCLK,
|
||||
.src_0 = &clk_xtal,
|
||||
.src_1 = &clk_ext,
|
||||
}, {
|
||||
.clk = &clk_urefclk,
|
||||
.bit = S3C2412_CLKSRC_UREFCLK_EXTCLK,
|
||||
.src_0 = &clk_xtal,
|
||||
.src_1 = &clk_ext,
|
||||
},
|
||||
};
|
||||
|
||||
/* s3c2412_clk_initparents
|
||||
*
|
||||
* Initialise the parents for the clocks that we get at start-time
|
||||
*/
|
||||
|
||||
static void __init s3c2412_clk_initparents(void)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
|
||||
struct clk_init *cip = clks_src;
|
||||
struct clk *src;
|
||||
int ptr;
|
||||
int ret;
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
|
||||
ret = s3c24xx_register_clock(cip->clk);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register clock %s (%d)\n",
|
||||
cip->clk->name, ret);
|
||||
}
|
||||
|
||||
src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
|
||||
|
||||
printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
|
||||
clk_set_parent(cip->clk, src);
|
||||
}
|
||||
}
|
||||
|
||||
/* clocks to add straight away */
|
||||
|
||||
static struct clk *clks[] __initdata = {
|
||||
&clk_ext,
|
||||
&clk_usb_bus,
|
||||
&clk_mrefclk,
|
||||
&clk_armclk,
|
||||
};
|
||||
|
||||
static struct clk_lookup s3c2412_clk_lookup[] = {
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_usysclk),
|
||||
};
|
||||
|
||||
int __init s3c2412_baseclk_add(void)
|
||||
{
|
||||
unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
|
||||
unsigned int dvs;
|
||||
struct clk *clkp;
|
||||
int ret;
|
||||
int ptr;
|
||||
|
||||
clk_upll.enable = s3c2412_upll_enable;
|
||||
clk_usb_bus.parent = &clk_usbsrc;
|
||||
clk_usb_bus.rate = 0x0;
|
||||
|
||||
clk_f.parent = &clk_msysclk;
|
||||
|
||||
s3c2412_clk_initparents();
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
|
||||
clkp = clks[ptr];
|
||||
|
||||
ret = s3c24xx_register_clock(clkp);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register clock %s (%d)\n",
|
||||
clkp->name, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* set the dvs state according to what we got at boot time */
|
||||
|
||||
dvs = __raw_readl(S3C2410_CLKDIVN) & S3C2412_CLKDIVN_DVSEN;
|
||||
|
||||
if (dvs)
|
||||
clk_armclk.parent = &clk_h;
|
||||
|
||||
printk(KERN_INFO "S3C2412: DVS is %s\n", dvs ? "on" : "off");
|
||||
|
||||
/* ensure usb bus clock is within correct rate of 48MHz */
|
||||
|
||||
if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
|
||||
printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
|
||||
|
||||
/* for the moment, let's use the UPLL, and see if we can
|
||||
* get 48MHz */
|
||||
|
||||
clk_set_parent(&clk_usysclk, &clk_upll);
|
||||
clk_set_parent(&clk_usbsrc, &clk_usysclk);
|
||||
clk_set_rate(&clk_usbsrc, 48*1000*1000);
|
||||
}
|
||||
|
||||
printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
|
||||
(__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
|
||||
print_mhz(clk_get_rate(&clk_upll)),
|
||||
print_mhz(clk_get_rate(&clk_usb_bus)));
|
||||
|
||||
/* register clocks from clock array */
|
||||
|
||||
clkp = init_clocks;
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
|
||||
/* ensure that we note the clock state */
|
||||
|
||||
clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
|
||||
|
||||
ret = s3c24xx_register_clock(clkp);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register clock %s (%d)\n",
|
||||
clkp->name, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* We must be careful disabling the clocks we are not intending to
|
||||
* be using at boot time, as subsystems such as the LCD which do
|
||||
* their own DMA requests to the bus can cause the system to lockup
|
||||
* if they where in the middle of requesting bus access.
|
||||
*
|
||||
* Disabling the LCD clock if the LCD is active is very dangerous,
|
||||
* and therefore the bootloader should be careful to not enable
|
||||
* the LCD clock if it is not needed.
|
||||
*/
|
||||
|
||||
/* install (and disable) the clocks we do not need immediately */
|
||||
|
||||
clkp = init_clocks_disable;
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
|
||||
|
||||
ret = s3c24xx_register_clock(clkp);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register clock %s (%d)\n",
|
||||
clkp->name, ret);
|
||||
}
|
||||
|
||||
s3c2412_clkcon_enable(clkp, 0);
|
||||
}
|
||||
|
||||
clkdev_add_table(s3c2412_clk_lookup, ARRAY_SIZE(s3c2412_clk_lookup));
|
||||
return 0;
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/* linux/arch/arm/mach-s3c2416/clock.c
|
||||
*
|
||||
* Copyright (c) 2010 Simtec Electronics
|
||||
* Copyright (c) 2010 Ben Dooks <ben-linux@fluff.org>
|
||||
*
|
||||
* S3C2416 Clock control support
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/clock-clksrc.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include <plat/cpu-freq.h>
|
||||
#include <plat/pll.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/regs-s3c2443-clock.h>
|
||||
|
||||
/* armdiv
|
||||
*
|
||||
* this clock is sourced from msysclk and can have a number of
|
||||
* divider values applied to it to then be fed into armclk.
|
||||
* The real clock definition is done in s3c2443-clock.c,
|
||||
* only the armdiv divisor table must be defined here.
|
||||
*/
|
||||
|
||||
static unsigned int armdiv[8] = {
|
||||
[0] = 1,
|
||||
[1] = 2,
|
||||
[2] = 3,
|
||||
[3] = 4,
|
||||
[5] = 6,
|
||||
[7] = 8,
|
||||
};
|
||||
|
||||
static struct clksrc_clk hsspi_eplldiv = {
|
||||
.clk = {
|
||||
.name = "hsspi-eplldiv",
|
||||
.parent = &clk_esysclk.clk,
|
||||
.ctrlbit = (1 << 14),
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 },
|
||||
};
|
||||
|
||||
static struct clk *hsspi_sources[] = {
|
||||
[0] = &hsspi_eplldiv.clk,
|
||||
[1] = NULL, /* to fix */
|
||||
};
|
||||
|
||||
static struct clksrc_clk hsspi_mux = {
|
||||
.clk = {
|
||||
.name = "hsspi-if",
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.sources = hsspi_sources,
|
||||
.nr_sources = ARRAY_SIZE(hsspi_sources),
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk hsmmc_div[] = {
|
||||
[0] = {
|
||||
.clk = {
|
||||
.name = "hsmmc-div",
|
||||
.devname = "s3c-sdhci.0",
|
||||
.parent = &clk_esysclk.clk,
|
||||
},
|
||||
.reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 },
|
||||
},
|
||||
[1] = {
|
||||
.clk = {
|
||||
.name = "hsmmc-div",
|
||||
.devname = "s3c-sdhci.1",
|
||||
.parent = &clk_esysclk.clk,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct clksrc_clk hsmmc_mux0 = {
|
||||
.clk = {
|
||||
.name = "hsmmc-if",
|
||||
.devname = "s3c-sdhci.0",
|
||||
.ctrlbit = (1 << 6),
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.nr_sources = 2,
|
||||
.sources = (struct clk * []) {
|
||||
[0] = &hsmmc_div[0].clk,
|
||||
[1] = NULL, /* to fix */
|
||||
},
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 },
|
||||
};
|
||||
|
||||
static struct clksrc_clk hsmmc_mux1 = {
|
||||
.clk = {
|
||||
.name = "hsmmc-if",
|
||||
.devname = "s3c-sdhci.1",
|
||||
.ctrlbit = (1 << 12),
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.nr_sources = 2,
|
||||
.sources = (struct clk * []) {
|
||||
[0] = &hsmmc_div[1].clk,
|
||||
[1] = NULL, /* to fix */
|
||||
},
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 },
|
||||
};
|
||||
|
||||
static struct clk hsmmc0_clk = {
|
||||
.name = "hsmmc",
|
||||
.devname = "s3c-sdhci.0",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2416_HCLKCON_HSMMC0,
|
||||
};
|
||||
|
||||
static struct clksrc_clk *clksrcs[] __initdata = {
|
||||
&hsspi_eplldiv,
|
||||
&hsspi_mux,
|
||||
&hsmmc_div[0],
|
||||
&hsmmc_div[1],
|
||||
&hsmmc_mux0,
|
||||
&hsmmc_mux1,
|
||||
};
|
||||
|
||||
static struct clk_lookup s3c2416_clk_lookup[] = {
|
||||
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk),
|
||||
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk),
|
||||
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk),
|
||||
/* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */
|
||||
CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk),
|
||||
};
|
||||
|
||||
void __init s3c2416_init_clocks(int xtal)
|
||||
{
|
||||
u32 epllcon = __raw_readl(S3C2443_EPLLCON);
|
||||
u32 epllcon1 = __raw_readl(S3C2443_EPLLCON+4);
|
||||
int ptr;
|
||||
|
||||
/* s3c2416 EPLL compatible with s3c64xx */
|
||||
clk_epll.rate = s3c_get_pll6553x(xtal, epllcon, epllcon1);
|
||||
|
||||
clk_epll.parent = &clk_epllref.clk;
|
||||
|
||||
s3c2443_common_init_clocks(xtal, s3c2416_get_pll,
|
||||
armdiv, ARRAY_SIZE(armdiv),
|
||||
S3C2416_CLKDIV0_ARMDIV_MASK);
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
|
||||
s3c_register_clksrc(clksrcs[ptr], 1);
|
||||
|
||||
s3c24xx_register_clock(&hsmmc0_clk);
|
||||
clkdev_add_table(s3c2416_clk_lookup, ARRAY_SIZE(s3c2416_clk_lookup));
|
||||
|
||||
}
|
@ -1,217 +0,0 @@
|
||||
/* linux/arch/arm/mach-s3c2440/clock.c
|
||||
*
|
||||
* Copyright (c) 2004-2005 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2440 Clock support
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/regs-clock.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
/* S3C2440 extended clock support */
|
||||
|
||||
static unsigned long s3c2440_camif_upll_round(struct clk *clk,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
int div;
|
||||
|
||||
if (rate > parent_rate)
|
||||
return parent_rate;
|
||||
|
||||
/* note, we remove the +/- 1 calculations for the divisor */
|
||||
|
||||
div = (parent_rate / rate) / 2;
|
||||
|
||||
if (div < 1)
|
||||
div = 1;
|
||||
else if (div > 16)
|
||||
div = 16;
|
||||
|
||||
return parent_rate / (div * 2);
|
||||
}
|
||||
|
||||
static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||
|
||||
rate = s3c2440_camif_upll_round(clk, rate);
|
||||
|
||||
camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK);
|
||||
|
||||
if (rate != parent_rate) {
|
||||
camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
|
||||
camdivn |= (((parent_rate / rate) / 2) - 1);
|
||||
}
|
||||
|
||||
__raw_writel(camdivn, S3C2440_CAMDIVN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long s3c2440_camif_upll_getrate(struct clk *clk)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||
|
||||
if (!(camdivn & S3C2440_CAMDIVN_CAMCLK_SEL))
|
||||
return parent_rate;
|
||||
|
||||
camdivn &= S3C2440_CAMDIVN_CAMCLK_MASK;
|
||||
|
||||
return parent_rate / (camdivn + 1) / 2;
|
||||
}
|
||||
|
||||
/* Extra S3C2440 clocks */
|
||||
|
||||
static struct clk s3c2440_clk_cam = {
|
||||
.name = "camif",
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_cam_upll = {
|
||||
.name = "camif-upll",
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_rate = s3c2440_camif_upll_setrate,
|
||||
.get_rate = s3c2440_camif_upll_getrate,
|
||||
.round_rate = s3c2440_camif_upll_round,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk s3c2440_clk_ac97 = {
|
||||
.name = "ac97",
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_AC97,
|
||||
};
|
||||
|
||||
#define S3C24XX_VA_UART0 (S3C_VA_UART)
|
||||
#define S3C24XX_VA_UART1 (S3C_VA_UART + 0x4000 )
|
||||
#define S3C24XX_VA_UART2 (S3C_VA_UART + 0x8000 )
|
||||
#define S3C24XX_VA_UART3 (S3C_VA_UART + 0xC000 )
|
||||
|
||||
static unsigned long s3c2440_fclk_n_getrate(struct clk *clk)
|
||||
{
|
||||
unsigned long ucon0, ucon1, ucon2, divisor;
|
||||
|
||||
/* the fun of calculating the uart divisors on the s3c2440 */
|
||||
ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
|
||||
ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
|
||||
ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
|
||||
|
||||
ucon0 &= S3C2440_UCON0_DIVMASK;
|
||||
ucon1 &= S3C2440_UCON1_DIVMASK;
|
||||
ucon2 &= S3C2440_UCON2_DIVMASK;
|
||||
|
||||
if (ucon0 != 0)
|
||||
divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6;
|
||||
else if (ucon1 != 0)
|
||||
divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21;
|
||||
else if (ucon2 != 0)
|
||||
divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36;
|
||||
else
|
||||
/* manual calims 44, seems to be 9 */
|
||||
divisor = 9;
|
||||
|
||||
return clk_get_rate(clk->parent) / divisor;
|
||||
}
|
||||
|
||||
static struct clk s3c2440_clk_fclk_n = {
|
||||
.name = "fclk_n",
|
||||
.parent = &clk_f,
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2440_fclk_n_getrate,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_lookup s3c2440_clk_lookup[] = {
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
|
||||
CLKDEV_INIT("s3c2440-uart.0", "uart", &s3c24xx_clk_uart0),
|
||||
CLKDEV_INIT("s3c2440-uart.1", "uart", &s3c24xx_clk_uart1),
|
||||
CLKDEV_INIT("s3c2440-uart.2", "uart", &s3c24xx_clk_uart2),
|
||||
CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll),
|
||||
};
|
||||
|
||||
static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
|
||||
{
|
||||
struct clk *clock_upll;
|
||||
struct clk *clock_h;
|
||||
struct clk *clock_p;
|
||||
|
||||
clock_p = clk_get(NULL, "pclk");
|
||||
clock_h = clk_get(NULL, "hclk");
|
||||
clock_upll = clk_get(NULL, "upll");
|
||||
|
||||
if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
|
||||
printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2440_clk_cam.parent = clock_h;
|
||||
s3c2440_clk_ac97.parent = clock_p;
|
||||
s3c2440_clk_cam_upll.parent = clock_upll;
|
||||
s3c24xx_register_clock(&s3c2440_clk_fclk_n);
|
||||
|
||||
s3c24xx_register_clock(&s3c2440_clk_ac97);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2440_clk_cam_upll);
|
||||
clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup));
|
||||
|
||||
clk_disable(&s3c2440_clk_ac97);
|
||||
clk_disable(&s3c2440_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct subsys_interface s3c2440_clk_interface = {
|
||||
.name = "s3c2440_clk",
|
||||
.subsys = &s3c2440_subsys,
|
||||
.add_dev = s3c2440_clk_add,
|
||||
};
|
||||
|
||||
static __init int s3c24xx_clk_init(void)
|
||||
{
|
||||
return subsys_interface_register(&s3c2440_clk_interface);
|
||||
}
|
||||
|
||||
arch_initcall(s3c24xx_clk_init);
|
@ -1,212 +0,0 @@
|
||||
/* linux/arch/arm/mach-s3c2443/clock.c
|
||||
*
|
||||
* Copyright (c) 2007, 2010 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2443 Clock control support
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include <mach/regs-s3c2443-clock.h>
|
||||
|
||||
#include <plat/cpu-freq.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/clock-clksrc.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
/* We currently have to assume that the system is running
|
||||
* from the XTPll input, and that all ***REFCLKs are being
|
||||
* fed from it, as we cannot read the state of OM[4] from
|
||||
* software.
|
||||
*
|
||||
* It would be possible for each board initialisation to
|
||||
* set the correct muxing at initialisation
|
||||
*/
|
||||
|
||||
/* clock selections */
|
||||
|
||||
/* armdiv
|
||||
*
|
||||
* this clock is sourced from msysclk and can have a number of
|
||||
* divider values applied to it to then be fed into armclk.
|
||||
* The real clock definition is done in s3c2443-clock.c,
|
||||
* only the armdiv divisor table must be defined here.
|
||||
*/
|
||||
|
||||
static unsigned int armdiv[16] = {
|
||||
[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1,
|
||||
[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2,
|
||||
[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3,
|
||||
[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4,
|
||||
[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6,
|
||||
[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8,
|
||||
[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12,
|
||||
[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16,
|
||||
};
|
||||
|
||||
/* hsspi
|
||||
*
|
||||
* high-speed spi clock, sourced from esysclk
|
||||
*/
|
||||
|
||||
static struct clksrc_clk clk_hsspi = {
|
||||
.clk = {
|
||||
.name = "hsspi-if",
|
||||
.parent = &clk_esysclk.clk,
|
||||
.ctrlbit = S3C2443_SCLKCON_HSSPICLK,
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
|
||||
};
|
||||
|
||||
|
||||
/* clk_hsmcc_div
|
||||
*
|
||||
* this clock is sourced from epll, and is fed through a divider,
|
||||
* to a mux controlled by sclkcon where either it or a extclk can
|
||||
* be fed to the hsmmc block
|
||||
*/
|
||||
|
||||
static struct clksrc_clk clk_hsmmc_div = {
|
||||
.clk = {
|
||||
.name = "hsmmc-div",
|
||||
.devname = "s3c-sdhci.1",
|
||||
.parent = &clk_esysclk.clk,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
|
||||
};
|
||||
|
||||
static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
|
||||
|
||||
clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
|
||||
S3C2443_SCLKCON_HSMMCCLK_EPLL);
|
||||
|
||||
if (parent == &clk_epll)
|
||||
clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
|
||||
else if (parent == &clk_ext)
|
||||
clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (clk->usage > 0) {
|
||||
__raw_writel(clksrc, S3C2443_SCLKCON);
|
||||
}
|
||||
|
||||
clk->parent = parent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
|
||||
{
|
||||
return s3c2443_setparent_hsmmc(clk, clk->parent);
|
||||
}
|
||||
|
||||
static struct clk clk_hsmmc = {
|
||||
.name = "hsmmc-if",
|
||||
.devname = "s3c-sdhci.1",
|
||||
.parent = &clk_hsmmc_div.clk,
|
||||
.enable = s3c2443_enable_hsmmc,
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_parent = s3c2443_setparent_hsmmc,
|
||||
},
|
||||
};
|
||||
|
||||
/* standard clock definitions */
|
||||
|
||||
static struct clk init_clocks_off[] = {
|
||||
{
|
||||
.name = "sdi",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_SDI,
|
||||
}, {
|
||||
.name = "spi",
|
||||
.devname = "s3c2410-spi.0",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_SPI1,
|
||||
}
|
||||
};
|
||||
|
||||
/* clocks to add straight away */
|
||||
|
||||
static struct clksrc_clk *clksrcs[] __initdata = {
|
||||
&clk_hsspi,
|
||||
&clk_hsmmc_div,
|
||||
};
|
||||
|
||||
static struct clk *clks[] __initdata = {
|
||||
&clk_hsmmc,
|
||||
};
|
||||
|
||||
static struct clk_lookup s3c2443_clk_lookup[] = {
|
||||
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc),
|
||||
CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk),
|
||||
};
|
||||
|
||||
void __init s3c2443_init_clocks(int xtal)
|
||||
{
|
||||
unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
|
||||
int ptr;
|
||||
|
||||
clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
|
||||
clk_epll.parent = &clk_epllref.clk;
|
||||
|
||||
s3c2443_common_init_clocks(xtal, s3c2443_get_mpll,
|
||||
armdiv, ARRAY_SIZE(armdiv),
|
||||
S3C2443_CLKDIV0_ARMDIV_MASK);
|
||||
|
||||
s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
|
||||
s3c_register_clksrc(clksrcs[ptr], 1);
|
||||
|
||||
/* We must be careful disabling the clocks we are not intending to
|
||||
* be using at boot time, as subsystems such as the LCD which do
|
||||
* their own DMA requests to the bus can cause the system to lockup
|
||||
* if they where in the middle of requesting bus access.
|
||||
*
|
||||
* Disabling the LCD clock if the LCD is active is very dangerous,
|
||||
* and therefore the bootloader should be careful to not enable
|
||||
* the LCD clock if it is not needed.
|
||||
*/
|
||||
|
||||
/* install (and disable) the clocks we do not need immediately */
|
||||
|
||||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup));
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c
|
||||
*
|
||||
* Copyright (c) 2004-2008 Simtec Electronics
|
||||
* http://armlinux.simtec.co.uk/
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* S3C2440/S3C2442 Common clock support
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/regs-clock.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
unsigned long camdivn;
|
||||
unsigned long dvs;
|
||||
|
||||
if (parent == &clk_f)
|
||||
dvs = 0;
|
||||
else if (parent == &clk_h)
|
||||
dvs = S3C2440_CAMDIVN_DVSEN;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
clk->parent = parent;
|
||||
|
||||
camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||
camdivn &= ~S3C2440_CAMDIVN_DVSEN;
|
||||
camdivn |= dvs;
|
||||
__raw_writel(camdivn, S3C2440_CAMDIVN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk clk_arm = {
|
||||
.name = "armclk",
|
||||
.id = -1,
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_parent = s3c2440_setparent_armclk,
|
||||
},
|
||||
};
|
||||
|
||||
static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif)
|
||||
{
|
||||
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||
unsigned long clkdivn;
|
||||
struct clk *clock_upll;
|
||||
int ret;
|
||||
|
||||
printk("S3C244X: Clock Support, DVS %s\n",
|
||||
(camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
|
||||
|
||||
clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f;
|
||||
|
||||
ret = s3c24xx_register_clock(&clk_arm);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clock_upll = clk_get(NULL, "upll");
|
||||
if (IS_ERR(clock_upll)) {
|
||||
printk(KERN_ERR "S3C244X: Failed to get upll clock\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* check rate of UPLL, and if it is near 96MHz, then change
|
||||
* to using half the UPLL rate for the system */
|
||||
|
||||
if (clk_get_rate(clock_upll) > (94 * MHZ)) {
|
||||
clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
|
||||
|
||||
spin_lock(&clocks_lock);
|
||||
|
||||
clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||
clkdivn |= S3C2440_CLKDIVN_UCLK;
|
||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||
|
||||
spin_unlock(&clocks_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct subsys_interface s3c2440_clk_interface = {
|
||||
.name = "s3c2440_clk",
|
||||
.subsys = &s3c2440_subsys,
|
||||
.add_dev = s3c244x_clk_add,
|
||||
};
|
||||
|
||||
static int s3c2440_clk_init(void)
|
||||
{
|
||||
return subsys_interface_register(&s3c2440_clk_interface);
|
||||
}
|
||||
|
||||
arch_initcall(s3c2440_clk_init);
|
||||
|
||||
static struct subsys_interface s3c2442_clk_interface = {
|
||||
.name = "s3c2442_clk",
|
||||
.subsys = &s3c2442_subsys,
|
||||
.add_dev = s3c244x_clk_add,
|
||||
};
|
||||
|
||||
static int s3c2442_clk_init(void)
|
||||
{
|
||||
return subsys_interface_register(&s3c2442_clk_interface);
|
||||
}
|
||||
|
||||
arch_initcall(s3c2442_clk_init);
|
@ -1,675 +0,0 @@
|
||||
/*
|
||||
* Common code for SoCs starting with the S3C2443
|
||||
*
|
||||
* Copyright (c) 2007, 2010 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/regs-s3c2443-clock.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/clock-clksrc.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include <plat/cpu-freq.h>
|
||||
|
||||
|
||||
static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable)
|
||||
{
|
||||
u32 ctrlbit = clk->ctrlbit;
|
||||
u32 con = __raw_readl(reg);
|
||||
|
||||
if (enable)
|
||||
con |= ctrlbit;
|
||||
else
|
||||
con &= ~ctrlbit;
|
||||
|
||||
__raw_writel(con, reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
|
||||
{
|
||||
return s3c2443_gate(S3C2443_HCLKCON, clk, enable);
|
||||
}
|
||||
|
||||
int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
|
||||
{
|
||||
return s3c2443_gate(S3C2443_PCLKCON, clk, enable);
|
||||
}
|
||||
|
||||
int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
|
||||
{
|
||||
return s3c2443_gate(S3C2443_SCLKCON, clk, enable);
|
||||
}
|
||||
|
||||
/* mpllref is a direct descendant of clk_xtal by default, but it is not
|
||||
* elided as the EPLL can be either sourced by the XTAL or EXTCLK and as
|
||||
* such directly equating the two source clocks is impossible.
|
||||
*/
|
||||
static struct clk clk_mpllref = {
|
||||
.name = "mpllref",
|
||||
.parent = &clk_xtal,
|
||||
};
|
||||
|
||||
static struct clk *clk_epllref_sources[] = {
|
||||
[0] = &clk_mpllref,
|
||||
[1] = &clk_mpllref,
|
||||
[2] = &clk_xtal,
|
||||
[3] = &clk_ext,
|
||||
};
|
||||
|
||||
struct clksrc_clk clk_epllref = {
|
||||
.clk = {
|
||||
.name = "epllref",
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.sources = clk_epllref_sources,
|
||||
.nr_sources = ARRAY_SIZE(clk_epllref_sources),
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 },
|
||||
};
|
||||
|
||||
/* esysclk
|
||||
*
|
||||
* this is sourced from either the EPLL or the EPLLref clock
|
||||
*/
|
||||
|
||||
static struct clk *clk_sysclk_sources[] = {
|
||||
[0] = &clk_epllref.clk,
|
||||
[1] = &clk_epll,
|
||||
};
|
||||
|
||||
struct clksrc_clk clk_esysclk = {
|
||||
.clk = {
|
||||
.name = "esysclk",
|
||||
.parent = &clk_epll,
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.sources = clk_sysclk_sources,
|
||||
.nr_sources = ARRAY_SIZE(clk_sysclk_sources),
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 },
|
||||
};
|
||||
|
||||
static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long div = __raw_readl(S3C2443_CLKDIV0);
|
||||
|
||||
div &= S3C2443_CLKDIV0_EXTDIV_MASK;
|
||||
div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */
|
||||
|
||||
return parent_rate / (div + 1);
|
||||
}
|
||||
|
||||
static struct clk clk_mdivclk = {
|
||||
.name = "mdivclk",
|
||||
.parent = &clk_mpllref,
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2443_getrate_mdivclk,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk *clk_msysclk_sources[] = {
|
||||
[0] = &clk_mpllref,
|
||||
[1] = &clk_mpll,
|
||||
[2] = &clk_mdivclk,
|
||||
[3] = &clk_mpllref,
|
||||
};
|
||||
|
||||
static struct clksrc_clk clk_msysclk = {
|
||||
.clk = {
|
||||
.name = "msysclk",
|
||||
.parent = &clk_xtal,
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.sources = clk_msysclk_sources,
|
||||
.nr_sources = ARRAY_SIZE(clk_msysclk_sources),
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 },
|
||||
};
|
||||
|
||||
/* prediv
|
||||
*
|
||||
* this divides the msysclk down to pass to h/p/etc.
|
||||
*/
|
||||
|
||||
static unsigned long s3c2443_prediv_getrate(struct clk *clk)
|
||||
{
|
||||
unsigned long rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
|
||||
|
||||
clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK;
|
||||
clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
|
||||
|
||||
return rate / (clkdiv0 + 1);
|
||||
}
|
||||
|
||||
static struct clk clk_prediv = {
|
||||
.name = "prediv",
|
||||
.parent = &clk_msysclk.clk,
|
||||
.ops = &(struct clk_ops) {
|
||||
.get_rate = s3c2443_prediv_getrate,
|
||||
},
|
||||
};
|
||||
|
||||
/* hclk divider
|
||||
*
|
||||
* divides the prediv and provides the hclk.
|
||||
*/
|
||||
|
||||
static unsigned long s3c2443_hclkdiv_getrate(struct clk *clk)
|
||||
{
|
||||
unsigned long rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
|
||||
|
||||
clkdiv0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
|
||||
|
||||
return rate / (clkdiv0 + 1);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_h_ops = {
|
||||
.get_rate = s3c2443_hclkdiv_getrate,
|
||||
};
|
||||
|
||||
/* pclk divider
|
||||
*
|
||||
* divides the hclk and provides the pclk.
|
||||
*/
|
||||
|
||||
static unsigned long s3c2443_pclkdiv_getrate(struct clk *clk)
|
||||
{
|
||||
unsigned long rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
|
||||
|
||||
clkdiv0 = ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 1 : 0);
|
||||
|
||||
return rate / (clkdiv0 + 1);
|
||||
}
|
||||
|
||||
static struct clk_ops clk_p_ops = {
|
||||
.get_rate = s3c2443_pclkdiv_getrate,
|
||||
};
|
||||
|
||||
/* armdiv
|
||||
*
|
||||
* this clock is sourced from msysclk and can have a number of
|
||||
* divider values applied to it to then be fed into armclk.
|
||||
*/
|
||||
|
||||
static unsigned int *armdiv;
|
||||
static int nr_armdiv;
|
||||
static int armdivmask;
|
||||
|
||||
static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long parent = clk_get_rate(clk->parent);
|
||||
unsigned long calc;
|
||||
unsigned best = 256; /* bigger than any value */
|
||||
unsigned div;
|
||||
int ptr;
|
||||
|
||||
if (!nr_armdiv)
|
||||
return -EINVAL;
|
||||
|
||||
for (ptr = 0; ptr < nr_armdiv; ptr++) {
|
||||
div = armdiv[ptr];
|
||||
if (div) {
|
||||
/* cpufreq provides 266mhz as 266666000 not 266666666 */
|
||||
calc = (parent / div / 1000) * 1000;
|
||||
if (calc <= rate && div < best)
|
||||
best = div;
|
||||
}
|
||||
}
|
||||
|
||||
return parent / best;
|
||||
}
|
||||
|
||||
static unsigned long s3c2443_armclk_getrate(struct clk *clk)
|
||||
{
|
||||
unsigned long rate = clk_get_rate(clk->parent);
|
||||
unsigned long clkcon0;
|
||||
int val;
|
||||
|
||||
if (!nr_armdiv || !armdivmask)
|
||||
return -EINVAL;
|
||||
|
||||
clkcon0 = __raw_readl(S3C2443_CLKDIV0);
|
||||
clkcon0 &= armdivmask;
|
||||
val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT;
|
||||
|
||||
return rate / armdiv[val];
|
||||
}
|
||||
|
||||
static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent = clk_get_rate(clk->parent);
|
||||
unsigned long calc;
|
||||
unsigned div;
|
||||
unsigned best = 256; /* bigger than any value */
|
||||
int ptr;
|
||||
int val = -1;
|
||||
|
||||
if (!nr_armdiv || !armdivmask)
|
||||
return -EINVAL;
|
||||
|
||||
for (ptr = 0; ptr < nr_armdiv; ptr++) {
|
||||
div = armdiv[ptr];
|
||||
if (div) {
|
||||
/* cpufreq provides 266mhz as 266666000 not 266666666 */
|
||||
calc = (parent / div / 1000) * 1000;
|
||||
if (calc <= rate && div < best) {
|
||||
best = div;
|
||||
val = ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val >= 0) {
|
||||
unsigned long clkcon0;
|
||||
|
||||
clkcon0 = __raw_readl(S3C2443_CLKDIV0);
|
||||
clkcon0 &= ~armdivmask;
|
||||
clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
|
||||
__raw_writel(clkcon0, S3C2443_CLKDIV0);
|
||||
}
|
||||
|
||||
return (val == -1) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static struct clk clk_armdiv = {
|
||||
.name = "armdiv",
|
||||
.parent = &clk_msysclk.clk,
|
||||
.ops = &(struct clk_ops) {
|
||||
.round_rate = s3c2443_armclk_roundrate,
|
||||
.get_rate = s3c2443_armclk_getrate,
|
||||
.set_rate = s3c2443_armclk_setrate,
|
||||
},
|
||||
};
|
||||
|
||||
/* armclk
|
||||
*
|
||||
* this is the clock fed into the ARM core itself, from armdiv or from hclk.
|
||||
*/
|
||||
|
||||
static struct clk *clk_arm_sources[] = {
|
||||
[0] = &clk_armdiv,
|
||||
[1] = &clk_h,
|
||||
};
|
||||
|
||||
static struct clksrc_clk clk_arm = {
|
||||
.clk = {
|
||||
.name = "armclk",
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.sources = clk_arm_sources,
|
||||
.nr_sources = ARRAY_SIZE(clk_arm_sources),
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
|
||||
};
|
||||
|
||||
/* usbhost
|
||||
*
|
||||
* usb host bus-clock, usually 48MHz to provide USB bus clock timing
|
||||
*/
|
||||
|
||||
static struct clksrc_clk clk_usb_bus_host = {
|
||||
.clk = {
|
||||
.name = "usb-bus-host-parent",
|
||||
.parent = &clk_esysclk.clk,
|
||||
.ctrlbit = S3C2443_SCLKCON_USBHOST,
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
|
||||
};
|
||||
|
||||
/* common clksrc clocks */
|
||||
|
||||
static struct clksrc_clk clksrc_clks[] = {
|
||||
{
|
||||
/* camera interface bus-clock, divided down from esysclk */
|
||||
.clk = {
|
||||
.name = "camif-upll", /* same as 2440 name */
|
||||
.parent = &clk_esysclk.clk,
|
||||
.ctrlbit = S3C2443_SCLKCON_CAMCLK,
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 },
|
||||
}, {
|
||||
.clk = {
|
||||
.name = "display-if",
|
||||
.parent = &clk_esysclk.clk,
|
||||
.ctrlbit = S3C2443_SCLKCON_DISPCLK,
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct clksrc_clk clk_esys_uart = {
|
||||
/* ART baud-rate clock sourced from esysclk via a divisor */
|
||||
.clk = {
|
||||
.name = "uartclk",
|
||||
.parent = &clk_esysclk.clk,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
|
||||
};
|
||||
|
||||
static struct clk clk_i2s_ext = {
|
||||
.name = "i2s-ext",
|
||||
};
|
||||
|
||||
/* i2s_eplldiv
|
||||
*
|
||||
* This clock is the output from the I2S divisor of ESYSCLK, and is separate
|
||||
* from the mux that comes after it (cannot merge into one single clock)
|
||||
*/
|
||||
|
||||
static struct clksrc_clk clk_i2s_eplldiv = {
|
||||
.clk = {
|
||||
.name = "i2s-eplldiv",
|
||||
.parent = &clk_esysclk.clk,
|
||||
},
|
||||
.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
|
||||
};
|
||||
|
||||
/* i2s-ref
|
||||
*
|
||||
* i2s bus reference clock, selectable from external, esysclk or epllref
|
||||
*
|
||||
* Note, this used to be two clocks, but was compressed into one.
|
||||
*/
|
||||
|
||||
static struct clk *clk_i2s_srclist[] = {
|
||||
[0] = &clk_i2s_eplldiv.clk,
|
||||
[1] = &clk_i2s_ext,
|
||||
[2] = &clk_epllref.clk,
|
||||
[3] = &clk_epllref.clk,
|
||||
};
|
||||
|
||||
static struct clksrc_clk clk_i2s = {
|
||||
.clk = {
|
||||
.name = "i2s-if",
|
||||
.ctrlbit = S3C2443_SCLKCON_I2SCLK,
|
||||
.enable = s3c2443_clkcon_enable_s,
|
||||
|
||||
},
|
||||
.sources = &(struct clksrc_sources) {
|
||||
.sources = clk_i2s_srclist,
|
||||
.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
|
||||
},
|
||||
.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
|
||||
};
|
||||
|
||||
static struct clk init_clocks_off[] = {
|
||||
{
|
||||
.name = "iis",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_IIS,
|
||||
}, {
|
||||
.name = "adc",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_ADC,
|
||||
}, {
|
||||
.name = "i2c",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_IIC,
|
||||
}
|
||||
};
|
||||
|
||||
static struct clk init_clocks[] = {
|
||||
{
|
||||
.name = "dma.0",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_DMA0,
|
||||
}, {
|
||||
.name = "dma.1",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_DMA1,
|
||||
}, {
|
||||
.name = "dma.2",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_DMA2,
|
||||
}, {
|
||||
.name = "dma.3",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_DMA3,
|
||||
}, {
|
||||
.name = "dma.4",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_DMA4,
|
||||
}, {
|
||||
.name = "dma.5",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_DMA5,
|
||||
}, {
|
||||
.name = "gpio",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_GPIO,
|
||||
}, {
|
||||
.name = "usb-host",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_USBH,
|
||||
}, {
|
||||
.name = "usb-device",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_USBD,
|
||||
}, {
|
||||
.name = "lcd",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_LCDC,
|
||||
|
||||
}, {
|
||||
.name = "timers",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_PWMT,
|
||||
}, {
|
||||
.name = "cfc",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_CFC,
|
||||
}, {
|
||||
.name = "ssmc",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_SSMC,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2440-uart.0",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_UART0,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2440-uart.1",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_UART1,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2440-uart.2",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_UART2,
|
||||
}, {
|
||||
.name = "uart",
|
||||
.devname = "s3c2440-uart.3",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_UART3,
|
||||
}, {
|
||||
.name = "rtc",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_RTC,
|
||||
}, {
|
||||
.name = "watchdog",
|
||||
.parent = &clk_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_WDT,
|
||||
}, {
|
||||
.name = "ac97",
|
||||
.parent = &clk_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_AC97,
|
||||
}, {
|
||||
.name = "nand",
|
||||
.parent = &clk_h,
|
||||
}, {
|
||||
.name = "usb-bus-host",
|
||||
.parent = &clk_usb_bus_host.clk,
|
||||
}
|
||||
};
|
||||
|
||||
static struct clk hsmmc1_clk = {
|
||||
.name = "hsmmc",
|
||||
.devname = "s3c-sdhci.1",
|
||||
.parent = &clk_h,
|
||||
.enable = s3c2443_clkcon_enable_h,
|
||||
.ctrlbit = S3C2443_HCLKCON_HSMMC,
|
||||
};
|
||||
|
||||
static struct clk hsspi_clk = {
|
||||
.name = "spi",
|
||||
.devname = "s3c2443-spi.0",
|
||||
.parent = &clk_p,
|
||||
.enable = s3c2443_clkcon_enable_p,
|
||||
.ctrlbit = S3C2443_PCLKCON_HSSPI,
|
||||
};
|
||||
|
||||
/* EPLLCON compatible enough to get on/off information */
|
||||
|
||||
void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll)
|
||||
{
|
||||
unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
|
||||
unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
|
||||
struct clk *xtal_clk;
|
||||
unsigned long xtal;
|
||||
unsigned long pll;
|
||||
int ptr;
|
||||
|
||||
xtal_clk = clk_get(NULL, "xtal");
|
||||
xtal = clk_get_rate(xtal_clk);
|
||||
clk_put(xtal_clk);
|
||||
|
||||
pll = get_mpll(mpllcon, xtal);
|
||||
clk_msysclk.clk.rate = pll;
|
||||
clk_mpll.rate = pll;
|
||||
|
||||
printk("CPU: MPLL %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
|
||||
(mpllcon & S3C2443_PLLCON_OFF) ? "off" : "on",
|
||||
print_mhz(pll), print_mhz(clk_get_rate(&clk_armdiv)),
|
||||
print_mhz(clk_get_rate(&clk_h)),
|
||||
print_mhz(clk_get_rate(&clk_p)));
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++)
|
||||
s3c_set_clksrc(&clksrc_clks[ptr], true);
|
||||
|
||||
/* ensure usb bus clock is within correct rate of 48MHz */
|
||||
|
||||
if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) {
|
||||
printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
|
||||
clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000);
|
||||
}
|
||||
|
||||
printk("CPU: EPLL %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
|
||||
(epllcon & S3C2443_PLLCON_OFF) ? "off" : "on",
|
||||
print_mhz(clk_get_rate(&clk_epll)),
|
||||
print_mhz(clk_get_rate(&clk_usb_bus)));
|
||||
}
|
||||
|
||||
static struct clk *clks[] __initdata = {
|
||||
&clk_prediv,
|
||||
&clk_mpllref,
|
||||
&clk_mdivclk,
|
||||
&clk_ext,
|
||||
&clk_epll,
|
||||
&clk_usb_bus,
|
||||
&clk_armdiv,
|
||||
&hsmmc1_clk,
|
||||
&hsspi_clk,
|
||||
};
|
||||
|
||||
static struct clksrc_clk *clksrcs[] __initdata = {
|
||||
&clk_i2s_eplldiv,
|
||||
&clk_i2s,
|
||||
&clk_usb_bus_host,
|
||||
&clk_epllref,
|
||||
&clk_esysclk,
|
||||
&clk_msysclk,
|
||||
&clk_arm,
|
||||
};
|
||||
|
||||
static struct clk_lookup s3c2443_clk_lookup[] = {
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk),
|
||||
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk),
|
||||
CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk),
|
||||
};
|
||||
|
||||
void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
|
||||
unsigned int *divs, int nr_divs,
|
||||
int divmask)
|
||||
{
|
||||
int ptr;
|
||||
|
||||
armdiv = divs;
|
||||
nr_armdiv = nr_divs;
|
||||
armdivmask = divmask;
|
||||
|
||||
/* s3c2443 parents h clock from prediv */
|
||||
clk_h.parent = &clk_prediv;
|
||||
clk_h.ops = &clk_h_ops;
|
||||
|
||||
/* and p clock from h clock */
|
||||
clk_p.parent = &clk_h;
|
||||
clk_p.ops = &clk_p_ops;
|
||||
|
||||
clk_usb_bus.parent = &clk_usb_bus_host.clk;
|
||||
clk_epll.parent = &clk_epllref.clk;
|
||||
|
||||
s3c24xx_register_baseclocks(xtal);
|
||||
s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
|
||||
|
||||
for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
|
||||
s3c_register_clksrc(clksrcs[ptr], 1);
|
||||
|
||||
s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks));
|
||||
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
|
||||
|
||||
/* See s3c2443/etc notes on disabling clocks at init time */
|
||||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup));
|
||||
|
||||
s3c2443_common_setup_clocks(get_mpll);
|
||||
}
|
@ -53,6 +53,7 @@
|
||||
#include <plat/cpu-freq.h>
|
||||
#include <plat/pll.h>
|
||||
#include <plat/pwm-core.h>
|
||||
#include <plat/watchdog-reset.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@ -73,7 +74,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32410000,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2410_map_io,
|
||||
.init_clocks = s3c2410_init_clocks,
|
||||
.init_uarts = s3c2410_init_uarts,
|
||||
.init = s3c2410_init,
|
||||
.name = name_s3c2410
|
||||
@ -82,7 +82,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32410002,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2410_map_io,
|
||||
.init_clocks = s3c2410_init_clocks,
|
||||
.init_uarts = s3c2410_init_uarts,
|
||||
.init = s3c2410a_init,
|
||||
.name = name_s3c2410a
|
||||
@ -91,7 +90,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32440000,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2440_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2440_init,
|
||||
.name = name_s3c2440
|
||||
@ -100,7 +98,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32440001,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2440_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2440_init,
|
||||
.name = name_s3c2440a
|
||||
@ -109,7 +106,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32440aaa,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2442_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2442_init,
|
||||
.name = name_s3c2442
|
||||
@ -118,7 +114,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32440aab,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2442_map_io,
|
||||
.init_clocks = s3c244x_init_clocks,
|
||||
.init_uarts = s3c244x_init_uarts,
|
||||
.init = s3c2442_init,
|
||||
.name = name_s3c2442b
|
||||
@ -127,7 +122,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32412001,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2412_map_io,
|
||||
.init_clocks = s3c2412_init_clocks,
|
||||
.init_uarts = s3c2412_init_uarts,
|
||||
.init = s3c2412_init,
|
||||
.name = name_s3c2412,
|
||||
@ -136,7 +130,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32412003,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2412_map_io,
|
||||
.init_clocks = s3c2412_init_clocks,
|
||||
.init_uarts = s3c2412_init_uarts,
|
||||
.init = s3c2412_init,
|
||||
.name = name_s3c2412,
|
||||
@ -145,7 +138,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32450003,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2416_map_io,
|
||||
.init_clocks = s3c2416_init_clocks,
|
||||
.init_uarts = s3c2416_init_uarts,
|
||||
.init = s3c2416_init,
|
||||
.name = name_s3c2416,
|
||||
@ -154,7 +146,6 @@ static struct cpu_table cpu_ids[] __initdata = {
|
||||
.idcode = 0x32443001,
|
||||
.idmask = 0xffffffff,
|
||||
.map_io = s3c2443_map_io,
|
||||
.init_clocks = s3c2443_init_clocks,
|
||||
.init_uarts = s3c2443_init_uarts,
|
||||
.init = s3c2443_init,
|
||||
.name = name_s3c2443,
|
||||
@ -316,21 +307,6 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
|
||||
},
|
||||
};
|
||||
|
||||
/* initialise all the clocks */
|
||||
|
||||
void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk,
|
||||
unsigned long hclk,
|
||||
unsigned long pclk)
|
||||
{
|
||||
clk_upll.rate = s3c24xx_get_pll(__raw_readl(S3C2410_UPLLCON),
|
||||
clk_xtal.rate);
|
||||
|
||||
clk_mpll.rate = fclk;
|
||||
clk_h.rate = hclk;
|
||||
clk_p.rate = pclk;
|
||||
clk_f.rate = fclk;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
|
||||
defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
|
||||
static struct resource s3c2410_dma_resource[] = {
|
||||
@ -534,3 +510,62 @@ struct platform_device s3c2443_device_dma = {
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2410)
|
||||
void __init s3c2410_init_clocks(int xtal)
|
||||
{
|
||||
s3c2410_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
|
||||
samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2412
|
||||
void __init s3c2412_init_clocks(int xtal)
|
||||
{
|
||||
s3c2412_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2416
|
||||
void __init s3c2416_init_clocks(int xtal)
|
||||
{
|
||||
s3c2443_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2440)
|
||||
void __init s3c2440_init_clocks(int xtal)
|
||||
{
|
||||
s3c2410_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR);
|
||||
samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2442)
|
||||
void __init s3c2442_init_clocks(int xtal)
|
||||
{
|
||||
s3c2410_common_clk_init(NULL, xtal, 2, S3C24XX_VA_CLKPWR);
|
||||
samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2443
|
||||
void __init s3c2443_init_clocks(int xtal)
|
||||
{
|
||||
s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2440) || \
|
||||
defined(CONFIG_CPU_S3C2442)
|
||||
static struct resource s3c2410_dclk_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(0x56000084, 0x4),
|
||||
};
|
||||
|
||||
struct platform_device s3c2410_device_dclk = {
|
||||
.name = "s3c2410-dclk",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s3c2410_dclk_resource),
|
||||
.resource = s3c2410_dclk_resource,
|
||||
};
|
||||
#endif
|
||||
|
@ -67,16 +67,15 @@ extern struct syscore_ops s3c2416_irq_syscore_ops;
|
||||
#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
|
||||
extern void s3c244x_map_io(void);
|
||||
extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
|
||||
extern void s3c244x_init_clocks(int xtal);
|
||||
extern void s3c244x_restart(enum reboot_mode mode, const char *cmd);
|
||||
#else
|
||||
#define s3c244x_init_clocks NULL
|
||||
#define s3c244x_init_uarts NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_S3C2440
|
||||
extern int s3c2440_init(void);
|
||||
extern void s3c2440_map_io(void);
|
||||
extern void s3c2440_init_clocks(int xtal);
|
||||
extern void s3c2440_init_irq(void);
|
||||
#else
|
||||
#define s3c2440_init NULL
|
||||
@ -86,6 +85,7 @@ extern void s3c2440_init_irq(void);
|
||||
#ifdef CONFIG_CPU_S3C2442
|
||||
extern int s3c2442_init(void);
|
||||
extern void s3c2442_map_io(void);
|
||||
extern void s3c2442_init_clocks(int xtal);
|
||||
extern void s3c2442_init_irq(void);
|
||||
#else
|
||||
#define s3c2442_init NULL
|
||||
@ -114,4 +114,21 @@ extern struct platform_device s3c2412_device_dma;
|
||||
extern struct platform_device s3c2440_device_dma;
|
||||
extern struct platform_device s3c2443_device_dma;
|
||||
|
||||
extern struct platform_device s3c2410_device_dclk;
|
||||
|
||||
#ifdef CONFIG_S3C2410_COMMON_CLK
|
||||
void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
int current_soc,
|
||||
void __iomem *reg_base);
|
||||
#endif
|
||||
#ifdef CONFIG_S3C2412_COMMON_CLK
|
||||
void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
unsigned long ext_f, void __iomem *reg_base);
|
||||
#endif
|
||||
#ifdef CONFIG_S3C2443_COMMON_CLK
|
||||
void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
int current_soc,
|
||||
void __iomem *reg_base);
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/regs-clock.h>
|
||||
@ -60,5 +61,6 @@ void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg)
|
||||
*/
|
||||
void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg)
|
||||
{
|
||||
__raw_writel(cfg->pll.driver_data, S3C2410_MPLLCON);
|
||||
if (!IS_ERR(cfg->mpll))
|
||||
clk_set_rate(cfg->mpll, cfg->pll.frequency);
|
||||
}
|
||||
|
@ -42,24 +42,6 @@
|
||||
#define S3C2410_CLKCON_IIS (1<<17)
|
||||
#define S3C2410_CLKCON_SPI (1<<18)
|
||||
|
||||
/* DCLKCON register addresses in gpio.h */
|
||||
|
||||
#define S3C2410_DCLKCON_DCLK0EN (1<<0)
|
||||
#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1)
|
||||
#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1)
|
||||
#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4)
|
||||
#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8)
|
||||
#define S3C2410_DCLKCON_DCLK0_DIV_MASK ((0xf)<<4)
|
||||
#define S3C2410_DCLKCON_DCLK0_CMP_MASK ((0xf)<<8)
|
||||
|
||||
#define S3C2410_DCLKCON_DCLK1EN (1<<16)
|
||||
#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17)
|
||||
#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17)
|
||||
#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20)
|
||||
#define S3C2410_DCLKCON_DCLK1_CMP(x) (((x) - 1) <<24)
|
||||
#define S3C2410_DCLKCON_DCLK1_DIV_MASK ((0xf) <<20)
|
||||
#define S3C2410_DCLKCON_DCLK1_CMP_MASK ((0xf) <<24)
|
||||
|
||||
#define S3C2410_CLKDIVN_PDIVN (1<<0)
|
||||
#define S3C2410_CLKDIVN_HDIVN (1<<1)
|
||||
|
||||
|
@ -457,9 +457,6 @@
|
||||
|
||||
/* miscellaneous control */
|
||||
#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
|
||||
#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
|
||||
|
||||
#define S3C24XX_DCLKCON S3C24XX_GPIOREG2(0x84)
|
||||
|
||||
/* see clock.h for dclk definitions */
|
||||
|
||||
|
@ -161,11 +161,16 @@ static struct platform_device *amlm5900_devices[] __initdata = {
|
||||
static void __init amlm5900_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init amlm5900_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FB_S3C2410
|
||||
static struct s3c2410fb_display __initdata amlm5900_lcd_info = {
|
||||
.width = 160,
|
||||
@ -241,6 +246,6 @@ MACHINE_START(AML_M5900, "AML_M5900")
|
||||
.map_io = amlm5900_map_io,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_machine = amlm5900_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = amlm5900_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -46,7 +46,6 @@
|
||||
|
||||
#include <net/ax88796.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <linux/platform_data/asoc-s3c24xx_simtec.h>
|
||||
@ -352,6 +351,7 @@ static struct platform_device anubis_device_sm501 = {
|
||||
/* Standard Anubis devices */
|
||||
|
||||
static struct platform_device *anubis_devices[] __initdata = {
|
||||
&s3c2410_device_dclk,
|
||||
&s3c_device_ohci,
|
||||
&s3c_device_wdt,
|
||||
&s3c_device_adc,
|
||||
@ -364,14 +364,6 @@ static struct platform_device *anubis_devices[] __initdata = {
|
||||
&anubis_device_sm501,
|
||||
};
|
||||
|
||||
static struct clk *anubis_clocks[] __initdata = {
|
||||
&s3c24xx_dclk0,
|
||||
&s3c24xx_dclk1,
|
||||
&s3c24xx_clkout0,
|
||||
&s3c24xx_clkout1,
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
/* I2C devices. */
|
||||
|
||||
static struct i2c_board_info anubis_i2c_devs[] __initdata = {
|
||||
@ -394,23 +386,7 @@ static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = {
|
||||
|
||||
static void __init anubis_map_io(void)
|
||||
{
|
||||
/* initialise the clocks */
|
||||
|
||||
s3c24xx_dclk0.parent = &clk_upll;
|
||||
s3c24xx_dclk0.rate = 12*1000*1000;
|
||||
|
||||
s3c24xx_dclk1.parent = &clk_upll;
|
||||
s3c24xx_dclk1.rate = 24*1000*1000;
|
||||
|
||||
s3c24xx_clkout0.parent = &s3c24xx_dclk0;
|
||||
s3c24xx_clkout1.parent = &s3c24xx_dclk1;
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
|
||||
|
||||
s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
|
||||
@ -428,6 +404,12 @@ static void __init anubis_map_io(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init anubis_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init anubis_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -447,6 +429,6 @@ MACHINE_START(ANUBIS, "Simtec-Anubis")
|
||||
.map_io = anubis_map_io,
|
||||
.init_machine = anubis_init,
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = anubis_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include <linux/mtd/nand_ecc.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <linux/platform_data/mmc-s3cmci.h>
|
||||
@ -192,11 +191,16 @@ static struct platform_device *at2440evb_devices[] __initdata = {
|
||||
static void __init at2440evb_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
|
||||
s3c24xx_init_clocks(16934400);
|
||||
s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init at2440evb_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(16934400);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init at2440evb_init(void)
|
||||
{
|
||||
s3c24xx_fb_set_platdata(&at2440evb_fb_info);
|
||||
@ -213,6 +217,6 @@ MACHINE_START(AT2440EVB, "AT2440EVB")
|
||||
.map_io = at2440evb_map_io,
|
||||
.init_machine = at2440evb_init,
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = at2440evb_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <mach/gpio-samsung.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/cpu-freq.h>
|
||||
#include <plat/devs.h>
|
||||
@ -523,6 +522,7 @@ static struct s3c_hwmon_pdata bast_hwmon_info = {
|
||||
// cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0
|
||||
|
||||
static struct platform_device *bast_devices[] __initdata = {
|
||||
&s3c2410_device_dclk,
|
||||
&s3c_device_ohci,
|
||||
&s3c_device_lcd,
|
||||
&s3c_device_wdt,
|
||||
@ -537,14 +537,6 @@ static struct platform_device *bast_devices[] __initdata = {
|
||||
&bast_sio,
|
||||
};
|
||||
|
||||
static struct clk *bast_clocks[] __initdata = {
|
||||
&s3c24xx_dclk0,
|
||||
&s3c24xx_dclk1,
|
||||
&s3c24xx_clkout0,
|
||||
&s3c24xx_clkout1,
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static struct s3c_cpufreq_board __initdata bast_cpufreq = {
|
||||
.refresh = 7800, /* 7.8usec */
|
||||
.auto_io = 1,
|
||||
@ -558,29 +550,19 @@ static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = {
|
||||
|
||||
static void __init bast_map_io(void)
|
||||
{
|
||||
/* initialise the clocks */
|
||||
|
||||
s3c24xx_dclk0.parent = &clk_upll;
|
||||
s3c24xx_dclk0.rate = 12*1000*1000;
|
||||
|
||||
s3c24xx_dclk1.parent = &clk_upll;
|
||||
s3c24xx_dclk1.rate = 24*1000*1000;
|
||||
|
||||
s3c24xx_clkout0.parent = &s3c24xx_dclk0;
|
||||
s3c24xx_clkout1.parent = &s3c24xx_dclk1;
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
|
||||
|
||||
s3c_hwmon_set_platdata(&bast_hwmon_info);
|
||||
|
||||
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init bast_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init bast_init(void)
|
||||
{
|
||||
register_syscore_ops(&bast_pm_syscore_ops);
|
||||
@ -608,6 +590,6 @@ MACHINE_START(BAST, "Simtec-BAST")
|
||||
.map_io = bast_map_io,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_machine = bast_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = bast_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -501,7 +501,6 @@ static struct platform_device gta02_buttons_device = {
|
||||
static void __init gta02_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
@ -585,6 +584,11 @@ static void __init gta02_machine_init(void)
|
||||
regulator_has_full_constraints();
|
||||
}
|
||||
|
||||
static void __init gta02_init_time(void)
|
||||
{
|
||||
s3c2442_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
MACHINE_START(NEO1973_GTA02, "GTA02")
|
||||
/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
|
||||
@ -592,6 +596,6 @@ MACHINE_START(NEO1973_GTA02, "GTA02")
|
||||
.map_io = gta02_map_io,
|
||||
.init_irq = s3c2442_init_irq,
|
||||
.init_machine = gta02_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = gta02_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -57,7 +57,6 @@
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <mach/gpio-samsung.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/gpio-cfg.h>
|
||||
@ -646,7 +645,6 @@ static struct platform_device *h1940_devices[] __initdata = {
|
||||
static void __init h1940_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
|
||||
@ -662,6 +660,12 @@ static void __init h1940_map_io(void)
|
||||
WARN_ON(gpiochip_add(&h1940_latch_gpiochip));
|
||||
}
|
||||
|
||||
static void __init h1940_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
/* H1940 and RX3715 need to reserve this for suspend */
|
||||
static void __init h1940_reserve(void)
|
||||
{
|
||||
@ -739,6 +743,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
|
||||
.reserve = h1940_reserve,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_machine = h1940_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = h1940_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -507,11 +507,16 @@ static struct syscore_ops jive_pm_syscore_ops = {
|
||||
static void __init jive_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init jive_init_time(void)
|
||||
{
|
||||
s3c2412_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void jive_power_off(void)
|
||||
{
|
||||
printk(KERN_INFO "powering system down...\n");
|
||||
@ -665,6 +670,6 @@ MACHINE_START(JIVE, "JIVE")
|
||||
.init_irq = s3c2412_init_irq,
|
||||
.map_io = jive_map_io,
|
||||
.init_machine = jive_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = jive_init_time,
|
||||
.restart = s3c2412_restart,
|
||||
MACHINE_END
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/clock.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/samsung-time.h>
|
||||
@ -525,11 +524,16 @@ static struct platform_device *mini2440_devices[] __initdata = {
|
||||
static void __init mini2440_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init mini2440_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* mini2440_features string
|
||||
*
|
||||
@ -690,6 +694,6 @@ MACHINE_START(MINI2440, "MINI2440")
|
||||
.map_io = mini2440_map_io,
|
||||
.init_machine = mini2440_init,
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = mini2440_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -45,7 +45,6 @@
|
||||
|
||||
#include <linux/platform_data/i2c-s3c2410.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/devs.h>
|
||||
#include <linux/platform_data/mmc-s3cmci.h>
|
||||
@ -535,11 +534,16 @@ static void __init n30_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
|
||||
n30_hwinit();
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init n30_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
/* GPB3 is the line that controls the pull-up for the USB D+ line */
|
||||
|
||||
static void __init n30_init(void)
|
||||
@ -591,7 +595,7 @@ MACHINE_START(N30, "Acer-N30")
|
||||
Ben Dooks <ben-linux@fluff.org>
|
||||
*/
|
||||
.atag_offset = 0x100,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = n30_init_time,
|
||||
.init_machine = n30_init,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.map_io = n30_map_io,
|
||||
@ -602,7 +606,7 @@ MACHINE_START(N35, "Acer-N35")
|
||||
/* Maintainer: Christer Weinigel <christer@weinigel.se>
|
||||
*/
|
||||
.atag_offset = 0x100,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = n30_init_time,
|
||||
.init_machine = n30_init,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.map_io = n30_map_io,
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <linux/platform_data/i2c-s3c2410.h>
|
||||
|
||||
#include <plat/gpio-cfg.h>
|
||||
#include <plat/clock.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/samsung-time.h>
|
||||
@ -135,13 +134,18 @@ static void __init nexcoder_sensorboard_init(void)
|
||||
static void __init nexcoder_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
|
||||
nexcoder_sensorboard_init();
|
||||
}
|
||||
|
||||
static void __init nexcoder_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init nexcoder_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -154,6 +158,6 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
|
||||
.map_io = nexcoder_map_io,
|
||||
.init_machine = nexcoder_init,
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = nexcoder_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <linux/mtd/nand_ecc.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/cpu-freq.h>
|
||||
#include <plat/devs.h>
|
||||
@ -344,20 +343,13 @@ static struct i2c_board_info osiris_i2c_devs[] __initdata = {
|
||||
/* Standard Osiris devices */
|
||||
|
||||
static struct platform_device *osiris_devices[] __initdata = {
|
||||
&s3c2410_device_dclk,
|
||||
&s3c_device_i2c0,
|
||||
&s3c_device_wdt,
|
||||
&s3c_device_nand,
|
||||
&osiris_pcmcia,
|
||||
};
|
||||
|
||||
static struct clk *osiris_clocks[] __initdata = {
|
||||
&s3c24xx_dclk0,
|
||||
&s3c24xx_dclk1,
|
||||
&s3c24xx_clkout0,
|
||||
&s3c24xx_clkout1,
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static struct s3c_cpufreq_board __initdata osiris_cpufreq = {
|
||||
.refresh = 7800, /* refresh period is 7.8usec */
|
||||
.auto_io = 1,
|
||||
@ -368,23 +360,7 @@ static void __init osiris_map_io(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* initialise the clocks */
|
||||
|
||||
s3c24xx_dclk0.parent = &clk_upll;
|
||||
s3c24xx_dclk0.rate = 12*1000*1000;
|
||||
|
||||
s3c24xx_dclk1.parent = &clk_upll;
|
||||
s3c24xx_dclk1.rate = 24*1000*1000;
|
||||
|
||||
s3c24xx_clkout0.parent = &s3c24xx_dclk0;
|
||||
s3c24xx_clkout1.parent = &s3c24xx_dclk1;
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks));
|
||||
|
||||
s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
|
||||
@ -408,6 +384,12 @@ static void __init osiris_map_io(void)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __init osiris_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init osiris_init(void)
|
||||
{
|
||||
register_syscore_ops(&osiris_pm_syscore_ops);
|
||||
@ -429,6 +411,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS")
|
||||
.map_io = osiris_map_io,
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.init_machine = osiris_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = osiris_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/samsung-time.h>
|
||||
@ -100,11 +99,16 @@ static struct platform_device *otom11_devices[] __initdata = {
|
||||
static void __init otom11_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init otom11_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init otom11_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -117,6 +121,6 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
|
||||
.map_io = otom11_map_io,
|
||||
.init_machine = otom11_init,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = otom11_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -304,11 +304,16 @@ __setup("tft=", qt2410_tft_setup);
|
||||
static void __init qt2410_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
|
||||
s3c24xx_init_clocks(12*1000*1000);
|
||||
s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init qt2410_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init qt2410_machine_init(void)
|
||||
{
|
||||
s3c_nand_set_platdata(&qt2410_nand_info);
|
||||
@ -346,6 +351,6 @@ MACHINE_START(QT2410, "QT2410")
|
||||
.map_io = qt2410_map_io,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_machine = qt2410_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = qt2410_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <mach/gpio-samsung.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/pm.h>
|
||||
@ -710,6 +709,7 @@ static struct i2c_board_info rx1950_i2c_devices[] = {
|
||||
};
|
||||
|
||||
static struct platform_device *rx1950_devices[] __initdata = {
|
||||
&s3c2410_device_dclk,
|
||||
&s3c_device_lcd,
|
||||
&s3c_device_wdt,
|
||||
&s3c_device_i2c0,
|
||||
@ -728,20 +728,9 @@ static struct platform_device *rx1950_devices[] __initdata = {
|
||||
&rx1950_leds,
|
||||
};
|
||||
|
||||
static struct clk *rx1950_clocks[] __initdata = {
|
||||
&s3c24xx_clkout0,
|
||||
&s3c24xx_clkout1,
|
||||
};
|
||||
|
||||
static void __init rx1950_map_io(void)
|
||||
{
|
||||
s3c24xx_clkout0.parent = &clk_h;
|
||||
s3c24xx_clkout1.parent = &clk_f;
|
||||
|
||||
s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks));
|
||||
|
||||
s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
|
||||
s3c24xx_init_clocks(16934000);
|
||||
s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
|
||||
@ -754,6 +743,12 @@ static void __init rx1950_map_io(void)
|
||||
s3c_pm_init();
|
||||
}
|
||||
|
||||
static void __init rx1950_init_time(void)
|
||||
{
|
||||
s3c2442_init_clocks(16934000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init rx1950_init_machine(void)
|
||||
{
|
||||
int i;
|
||||
@ -816,6 +811,6 @@ MACHINE_START(RX1950, "HP iPAQ RX1950")
|
||||
.reserve = rx1950_reserve,
|
||||
.init_irq = s3c2442_init_irq,
|
||||
.init_machine = rx1950_init_machine,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = rx1950_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include <mach/regs-lcd.h>
|
||||
#include <mach/gpio-samsung.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/pm.h>
|
||||
@ -179,11 +178,16 @@ static struct platform_device *rx3715_devices[] __initdata = {
|
||||
static void __init rx3715_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
|
||||
s3c24xx_init_clocks(16934000);
|
||||
s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init rx3715_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(16934000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
/* H1940 and RX3715 need to reserve this for suspend */
|
||||
static void __init rx3715_reserve(void)
|
||||
{
|
||||
@ -210,6 +214,6 @@ MACHINE_START(RX3715, "IPAQ-RX3715")
|
||||
.reserve = rx3715_reserve,
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.init_machine = rx3715_init_machine,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = rx3715_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_s3c.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
@ -29,48 +28,14 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* The following lookup table is used to override device names when devices
|
||||
* are registered from device tree. This is temporarily added to enable
|
||||
* device tree support addition for the S3C2416 architecture.
|
||||
*
|
||||
* For drivers that require platform data to be provided from the machine
|
||||
* file, a platform data pointer can also be supplied along with the
|
||||
* devices names. Usually, the platform data elements that cannot be parsed
|
||||
* from the device tree by the drivers (example: function pointers) are
|
||||
* supplied. But it should be noted that this is a temporary mechanism and
|
||||
* at some point, the drivers should be capable of parsing all the platform
|
||||
* data from the device tree.
|
||||
*/
|
||||
static const struct of_dev_auxdata s3c2416_auxdata_lookup[] __initconst = {
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART,
|
||||
"s3c2440-uart.0", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x4000,
|
||||
"s3c2440-uart.1", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x8000,
|
||||
"s3c2440-uart.2", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0xC000,
|
||||
"s3c2440-uart.3", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC0,
|
||||
"s3c-sdhci.0", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC1,
|
||||
"s3c-sdhci.1", NULL),
|
||||
OF_DEV_AUXDATA("samsung,s3c2440-i2c", S3C_PA_IIC,
|
||||
"s3c2440-i2c.0", NULL),
|
||||
{},
|
||||
};
|
||||
|
||||
static void __init s3c2416_dt_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(NULL, 0);
|
||||
s3c24xx_init_clocks(12000000);
|
||||
}
|
||||
|
||||
static void __init s3c2416_dt_machine_init(void)
|
||||
{
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
s3c2416_auxdata_lookup, NULL);
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
|
||||
s3c_pm_init();
|
||||
}
|
||||
|
||||
@ -86,6 +51,5 @@ DT_MACHINE_START(S3C2416_DT, "Samsung S3C2416 (Flattened Device Tree)")
|
||||
.map_io = s3c2416_dt_map_io,
|
||||
.init_irq = irqchip_init,
|
||||
.init_machine = s3c2416_dt_machine_init,
|
||||
.init_time = clocksource_of_init,
|
||||
.restart = s3c2416_restart,
|
||||
MACHINE_END
|
||||
|
@ -99,11 +99,16 @@ static struct platform_device *smdk2410_devices[] __initdata = {
|
||||
static void __init smdk2410_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init smdk2410_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init smdk2410_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -118,6 +123,6 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
|
||||
.map_io = smdk2410_map_io,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_machine = smdk2410_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = smdk2410_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -106,11 +106,16 @@ static void __init smdk2413_fixup(struct tag *tags, char **cmdline,
|
||||
static void __init smdk2413_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init smdk2413_init_time(void)
|
||||
{
|
||||
s3c2412_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init smdk2413_machine_init(void)
|
||||
{ /* Turn off suspend on both USB ports, and switch the
|
||||
* selectable USB port to USB device mode. */
|
||||
@ -159,6 +164,6 @@ MACHINE_START(SMDK2413, "SMDK2413")
|
||||
.init_irq = s3c2412_init_irq,
|
||||
.map_io = smdk2413_map_io,
|
||||
.init_machine = smdk2413_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = smdk2413_init_time,
|
||||
.restart = s3c2412_restart,
|
||||
MACHINE_END
|
||||
|
@ -219,10 +219,15 @@ static struct platform_device *smdk2416_devices[] __initdata = {
|
||||
&s3c2443_device_dma,
|
||||
};
|
||||
|
||||
static void __init smdk2416_init_time(void)
|
||||
{
|
||||
s3c2416_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init smdk2416_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
@ -257,6 +262,6 @@ MACHINE_START(SMDK2416, "SMDK2416")
|
||||
.init_irq = s3c2416_init_irq,
|
||||
.map_io = smdk2416_map_io,
|
||||
.init_machine = smdk2416_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = smdk2416_init_time,
|
||||
.restart = s3c2416_restart,
|
||||
MACHINE_END
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include <mach/fb.h>
|
||||
#include <linux/platform_data/i2c-s3c2410.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/samsung-time.h>
|
||||
@ -159,11 +158,16 @@ static struct platform_device *smdk2440_devices[] __initdata = {
|
||||
static void __init smdk2440_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
|
||||
s3c24xx_init_clocks(16934400);
|
||||
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init smdk2440_init_time(void)
|
||||
{
|
||||
s3c2440_init_clocks(16934400);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init smdk2440_machine_init(void)
|
||||
{
|
||||
s3c24xx_fb_set_platdata(&smdk2440_fb_info);
|
||||
@ -180,6 +184,6 @@ MACHINE_START(S3C2440, "SMDK2440")
|
||||
.init_irq = s3c2440_init_irq,
|
||||
.map_io = smdk2440_map_io,
|
||||
.init_machine = smdk2440_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = smdk2440_init_time,
|
||||
.restart = s3c244x_restart,
|
||||
MACHINE_END
|
||||
|
@ -121,11 +121,16 @@ static struct platform_device *smdk2443_devices[] __initdata = {
|
||||
static void __init smdk2443_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init smdk2443_init_time(void)
|
||||
{
|
||||
s3c2443_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init smdk2443_machine_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -145,6 +150,6 @@ MACHINE_START(SMDK2443, "SMDK2443")
|
||||
.init_irq = s3c2443_init_irq,
|
||||
.map_io = smdk2443_map_io,
|
||||
.init_machine = smdk2443_machine_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = smdk2443_init_time,
|
||||
.restart = s3c2443_restart,
|
||||
MACHINE_END
|
||||
|
@ -135,11 +135,16 @@ static struct platform_device *tct_hammer_devices[] __initdata = {
|
||||
static void __init tct_hammer_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init tct_hammer_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init tct_hammer_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -151,6 +156,6 @@ MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
|
||||
.map_io = tct_hammer_map_io,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_machine = tct_hammer_init,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = tct_hammer_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include <mach/regs-gpio.h>
|
||||
#include <mach/gpio-samsung.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/samsung-time.h>
|
||||
@ -286,6 +285,7 @@ static struct i2c_board_info vr1000_i2c_devs[] __initdata = {
|
||||
/* devices for this board */
|
||||
|
||||
static struct platform_device *vr1000_devices[] __initdata = {
|
||||
&s3c2410_device_dclk,
|
||||
&s3c_device_ohci,
|
||||
&s3c_device_lcd,
|
||||
&s3c_device_wdt,
|
||||
@ -299,14 +299,6 @@ static struct platform_device *vr1000_devices[] __initdata = {
|
||||
&vr1000_led3,
|
||||
};
|
||||
|
||||
static struct clk *vr1000_clocks[] __initdata = {
|
||||
&s3c24xx_dclk0,
|
||||
&s3c24xx_dclk1,
|
||||
&s3c24xx_clkout0,
|
||||
&s3c24xx_clkout1,
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static void vr1000_power_off(void)
|
||||
{
|
||||
gpio_direction_output(S3C2410_GPB(9), 1);
|
||||
@ -314,29 +306,19 @@ static void vr1000_power_off(void)
|
||||
|
||||
static void __init vr1000_map_io(void)
|
||||
{
|
||||
/* initialise clock sources */
|
||||
|
||||
s3c24xx_dclk0.parent = &clk_upll;
|
||||
s3c24xx_dclk0.rate = 12*1000*1000;
|
||||
|
||||
s3c24xx_dclk1.parent = NULL;
|
||||
s3c24xx_dclk1.rate = 3692307;
|
||||
|
||||
s3c24xx_clkout0.parent = &s3c24xx_dclk0;
|
||||
s3c24xx_clkout1.parent = &s3c24xx_dclk1;
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks));
|
||||
|
||||
pm_power_off = vr1000_power_off;
|
||||
|
||||
s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init vr1000_init_time(void)
|
||||
{
|
||||
s3c2410_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init vr1000_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -357,6 +339,6 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
|
||||
.map_io = vr1000_map_io,
|
||||
.init_machine = vr1000_init,
|
||||
.init_irq = s3c2410_init_irq,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = vr1000_init_time,
|
||||
.restart = s3c2410_restart,
|
||||
MACHINE_END
|
||||
|
@ -142,11 +142,16 @@ static void __init vstms_fixup(struct tag *tags, char **cmdline,
|
||||
static void __init vstms_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
|
||||
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
|
||||
}
|
||||
|
||||
static void __init vstms_init_time(void)
|
||||
{
|
||||
s3c2412_init_clocks(12000000);
|
||||
samsung_timer_init();
|
||||
}
|
||||
|
||||
static void __init vstms_init(void)
|
||||
{
|
||||
s3c_i2c0_set_platdata(NULL);
|
||||
@ -162,6 +167,6 @@ MACHINE_START(VSTMS, "VSTMS")
|
||||
.init_irq = s3c2412_init_irq,
|
||||
.init_machine = vstms_init,
|
||||
.map_io = vstms_map_io,
|
||||
.init_time = samsung_timer_init,
|
||||
.init_time = vstms_init_time,
|
||||
.restart = s3c2412_restart,
|
||||
MACHINE_END
|
||||
|
@ -51,9 +51,6 @@
|
||||
#define PFX "s3c24xx-pm: "
|
||||
|
||||
static struct sleep_save core_save[] = {
|
||||
SAVE_ITEM(S3C2410_LOCKTIME),
|
||||
SAVE_ITEM(S3C2410_CLKCON),
|
||||
|
||||
/* we restore the timings here, with the proviso that the board
|
||||
* brings the system up in an slower, or equal frequency setting
|
||||
* to the original system.
|
||||
@ -69,18 +66,6 @@ static struct sleep_save core_save[] = {
|
||||
SAVE_ITEM(S3C2410_BANKCON3),
|
||||
SAVE_ITEM(S3C2410_BANKCON4),
|
||||
SAVE_ITEM(S3C2410_BANKCON5),
|
||||
|
||||
#ifndef CONFIG_CPU_FREQ
|
||||
SAVE_ITEM(S3C2410_CLKDIVN),
|
||||
SAVE_ITEM(S3C2410_MPLLCON),
|
||||
SAVE_ITEM(S3C2410_REFRESH),
|
||||
#endif
|
||||
SAVE_ITEM(S3C2410_UPLLCON),
|
||||
SAVE_ITEM(S3C2410_CLKSLOW),
|
||||
};
|
||||
|
||||
static struct sleep_save misc_save[] = {
|
||||
SAVE_ITEM(S3C2410_DCLKCON),
|
||||
};
|
||||
|
||||
/* s3c_pm_check_resume_pin
|
||||
@ -140,12 +125,10 @@ void s3c_pm_configure_extint(void)
|
||||
void s3c_pm_restore_core(void)
|
||||
{
|
||||
s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
|
||||
s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
|
||||
}
|
||||
|
||||
void s3c_pm_save_core(void)
|
||||
{
|
||||
s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
|
||||
s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
|
||||
}
|
||||
|
||||
|
@ -85,62 +85,6 @@ void __init s3c2410_map_io(void)
|
||||
|
||||
void __init_or_cpufreq s3c2410_setup_clocks(void)
|
||||
{
|
||||
struct clk *xtal_clk;
|
||||
unsigned long tmp;
|
||||
unsigned long xtal;
|
||||
unsigned long fclk;
|
||||
unsigned long hclk;
|
||||
unsigned long pclk;
|
||||
|
||||
xtal_clk = clk_get(NULL, "xtal");
|
||||
xtal = clk_get_rate(xtal_clk);
|
||||
clk_put(xtal_clk);
|
||||
|
||||
/* now we've got our machine bits initialised, work out what
|
||||
* clocks we've got */
|
||||
|
||||
fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal);
|
||||
|
||||
tmp = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
/* work out clock scalings */
|
||||
|
||||
hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
|
||||
pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
|
||||
|
||||
/* print brieft summary of clocks, etc */
|
||||
|
||||
printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
|
||||
print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
|
||||
|
||||
/* initialise the clocks here, to allow other things like the
|
||||
* console to use them
|
||||
*/
|
||||
|
||||
s3c24xx_setup_clocks(fclk, hclk, pclk);
|
||||
}
|
||||
|
||||
/* fake ARMCLK for use with cpufreq, etc. */
|
||||
|
||||
static struct clk s3c2410_armclk = {
|
||||
.name = "armclk",
|
||||
.parent = &clk_f,
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk_lookup s3c2410_clk_lookup[] = {
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p),
|
||||
CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
|
||||
};
|
||||
|
||||
void __init s3c2410_init_clocks(int xtal)
|
||||
{
|
||||
s3c24xx_register_baseclocks(xtal);
|
||||
s3c2410_setup_clocks();
|
||||
s3c2410_baseclk_add();
|
||||
s3c24xx_register_clock(&s3c2410_armclk);
|
||||
clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup));
|
||||
samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
|
||||
}
|
||||
|
||||
struct bus_type s3c2410_subsys = {
|
||||
|
@ -173,49 +173,6 @@ void __init s3c2412_map_io(void)
|
||||
|
||||
void __init_or_cpufreq s3c2412_setup_clocks(void)
|
||||
{
|
||||
struct clk *xtal_clk;
|
||||
unsigned long tmp;
|
||||
unsigned long xtal;
|
||||
unsigned long fclk;
|
||||
unsigned long hclk;
|
||||
unsigned long pclk;
|
||||
|
||||
xtal_clk = clk_get(NULL, "xtal");
|
||||
xtal = clk_get_rate(xtal_clk);
|
||||
clk_put(xtal_clk);
|
||||
|
||||
/* now we've got our machine bits initialised, work out what
|
||||
* clocks we've got */
|
||||
|
||||
fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal * 2);
|
||||
|
||||
clk_mpll.rate = fclk;
|
||||
|
||||
tmp = __raw_readl(S3C2410_CLKDIVN);
|
||||
|
||||
/* work out clock scalings */
|
||||
|
||||
hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
|
||||
hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1);
|
||||
pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
|
||||
|
||||
/* print brieft summary of clocks, etc */
|
||||
|
||||
printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
|
||||
print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
|
||||
|
||||
s3c24xx_setup_clocks(fclk, hclk, pclk);
|
||||
}
|
||||
|
||||
void __init s3c2412_init_clocks(int xtal)
|
||||
{
|
||||
/* initialise the clocks here, to allow other things like the
|
||||
* console to use them
|
||||
*/
|
||||
|
||||
s3c24xx_register_baseclocks(xtal);
|
||||
s3c2412_setup_clocks();
|
||||
s3c2412_baseclk_add();
|
||||
}
|
||||
|
||||
/* need to register the subsystem before we actually register the device, and
|
||||
|
@ -53,117 +53,6 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* S3C2442 extended clock support */
|
||||
|
||||
static unsigned long s3c2442_camif_upll_round(struct clk *clk,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
int div;
|
||||
|
||||
if (rate > parent_rate)
|
||||
return parent_rate;
|
||||
|
||||
div = parent_rate / rate;
|
||||
|
||||
if (div == 3)
|
||||
return parent_rate / 3;
|
||||
|
||||
/* note, we remove the +/- 1 calculations for the divisor */
|
||||
|
||||
div /= 2;
|
||||
|
||||
if (div < 1)
|
||||
div = 1;
|
||||
else if (div > 16)
|
||||
div = 16;
|
||||
|
||||
return parent_rate / (div * 2);
|
||||
}
|
||||
|
||||
static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate = clk_get_rate(clk->parent);
|
||||
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||
|
||||
rate = s3c2442_camif_upll_round(clk, rate);
|
||||
|
||||
camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
|
||||
|
||||
if (rate == parent_rate) {
|
||||
camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
|
||||
} else if ((parent_rate / rate) == 3) {
|
||||
camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
|
||||
camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
|
||||
} else {
|
||||
camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
|
||||
camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
|
||||
camdivn |= (((parent_rate / rate) / 2) - 1);
|
||||
}
|
||||
|
||||
__raw_writel(camdivn, S3C2440_CAMDIVN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Extra S3C2442 clocks */
|
||||
|
||||
static struct clk s3c2442_clk_cam = {
|
||||
.name = "camif",
|
||||
.id = -1,
|
||||
.enable = s3c2410_clkcon_enable,
|
||||
.ctrlbit = S3C2440_CLKCON_CAMERA,
|
||||
};
|
||||
|
||||
static struct clk s3c2442_clk_cam_upll = {
|
||||
.name = "camif-upll",
|
||||
.id = -1,
|
||||
.ops = &(struct clk_ops) {
|
||||
.set_rate = s3c2442_camif_upll_setrate,
|
||||
.round_rate = s3c2442_camif_upll_round,
|
||||
},
|
||||
};
|
||||
|
||||
static int s3c2442_clk_add(struct device *dev, struct subsys_interface *sif)
|
||||
{
|
||||
struct clk *clock_upll;
|
||||
struct clk *clock_h;
|
||||
struct clk *clock_p;
|
||||
|
||||
clock_p = clk_get(NULL, "pclk");
|
||||
clock_h = clk_get(NULL, "hclk");
|
||||
clock_upll = clk_get(NULL, "upll");
|
||||
|
||||
if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
|
||||
printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s3c2442_clk_cam.parent = clock_h;
|
||||
s3c2442_clk_cam_upll.parent = clock_upll;
|
||||
|
||||
s3c24xx_register_clock(&s3c2442_clk_cam);
|
||||
s3c24xx_register_clock(&s3c2442_clk_cam_upll);
|
||||
|
||||
clk_disable(&s3c2442_clk_cam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct subsys_interface s3c2442_clk_interface = {
|
||||
.name = "s3c2442_clk",
|
||||
.subsys = &s3c2442_subsys,
|
||||
.add_dev = s3c2442_clk_add,
|
||||
};
|
||||
|
||||
static __init int s3c2442_clk_init(void)
|
||||
{
|
||||
return subsys_interface_register(&s3c2442_clk_interface);
|
||||
}
|
||||
|
||||
arch_initcall(s3c2442_clk_init);
|
||||
|
||||
|
||||
static struct device s3c2442_dev = {
|
||||
.bus = &s3c2442_subsys,
|
||||
};
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <plat/nand-core.h>
|
||||
#include <plat/watchdog-reset.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "regs-dsc.h"
|
||||
|
||||
static struct map_desc s3c244x_iodesc[] __initdata = {
|
||||
@ -74,67 +75,11 @@ void __init s3c244x_map_io(void)
|
||||
s3c_nand_setname("s3c2440-nand");
|
||||
s3c_device_ts.name = "s3c2440-ts";
|
||||
s3c_device_usbgadget.name = "s3c2440-usbgadget";
|
||||
s3c2410_device_dclk.name = "s3c2440-dclk";
|
||||
}
|
||||
|
||||
void __init_or_cpufreq s3c244x_setup_clocks(void)
|
||||
{
|
||||
struct clk *xtal_clk;
|
||||
unsigned long clkdiv;
|
||||
unsigned long camdiv;
|
||||
unsigned long xtal;
|
||||
unsigned long hclk, fclk, pclk;
|
||||
int hdiv = 1;
|
||||
|
||||
xtal_clk = clk_get(NULL, "xtal");
|
||||
xtal = clk_get_rate(xtal_clk);
|
||||
clk_put(xtal_clk);
|
||||
|
||||
fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
|
||||
|
||||
clkdiv = __raw_readl(S3C2410_CLKDIVN);
|
||||
camdiv = __raw_readl(S3C2440_CAMDIVN);
|
||||
|
||||
/* work out clock scalings */
|
||||
|
||||
switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
|
||||
case S3C2440_CLKDIVN_HDIVN_1:
|
||||
hdiv = 1;
|
||||
break;
|
||||
|
||||
case S3C2440_CLKDIVN_HDIVN_2:
|
||||
hdiv = 2;
|
||||
break;
|
||||
|
||||
case S3C2440_CLKDIVN_HDIVN_4_8:
|
||||
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
|
||||
break;
|
||||
|
||||
case S3C2440_CLKDIVN_HDIVN_3_6:
|
||||
hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
|
||||
break;
|
||||
}
|
||||
|
||||
hclk = fclk / hdiv;
|
||||
pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
|
||||
|
||||
/* print brief summary of clocks, etc */
|
||||
|
||||
printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
|
||||
print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
|
||||
|
||||
s3c24xx_setup_clocks(fclk, hclk, pclk);
|
||||
}
|
||||
|
||||
void __init s3c244x_init_clocks(int xtal)
|
||||
{
|
||||
/* initialise the clocks here, to allow other things like the
|
||||
* console to use them, and to add new ones after the initialisation
|
||||
*/
|
||||
|
||||
s3c24xx_register_baseclocks(xtal);
|
||||
s3c244x_setup_clocks();
|
||||
s3c2410_baseclk_add();
|
||||
samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG);
|
||||
}
|
||||
|
||||
/* Since the S3C2442 and S3C2440 share items, put both subsystems here */
|
||||
|
@ -119,6 +119,7 @@ struct s3c_plltab {
|
||||
struct s3c_cpufreq_config {
|
||||
struct s3c_freq freq;
|
||||
struct s3c_freq max;
|
||||
struct clk *mpll;
|
||||
struct cpufreq_frequency_table pll;
|
||||
struct s3c_clkdivs divs;
|
||||
struct s3c_cpufreq_info *info; /* for core, not drivers */
|
||||
|
@ -8,4 +8,8 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
|
||||
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
|
||||
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
|
||||
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
|
||||
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
|
||||
obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
|
||||
obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/delay.h>
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
@ -58,6 +59,72 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
|
||||
return rate_table[i - 1].rate;
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL2126 Clock Type
|
||||
*/
|
||||
|
||||
#define PLL2126_MDIV_MASK (0xff)
|
||||
#define PLL2126_PDIV_MASK (0x3f)
|
||||
#define PLL2126_SDIV_MASK (0x3)
|
||||
#define PLL2126_MDIV_SHIFT (16)
|
||||
#define PLL2126_PDIV_SHIFT (8)
|
||||
#define PLL2126_SDIV_SHIFT (0)
|
||||
|
||||
static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 pll_con, mdiv, pdiv, sdiv;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
|
||||
sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
|
||||
|
||||
fvco *= (mdiv + 8);
|
||||
do_div(fvco, (pdiv + 2) << sdiv);
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll2126_clk_ops = {
|
||||
.recalc_rate = samsung_pll2126_recalc_rate,
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL3000 Clock Type
|
||||
*/
|
||||
|
||||
#define PLL3000_MDIV_MASK (0xff)
|
||||
#define PLL3000_PDIV_MASK (0x3)
|
||||
#define PLL3000_SDIV_MASK (0x3)
|
||||
#define PLL3000_MDIV_SHIFT (16)
|
||||
#define PLL3000_PDIV_SHIFT (8)
|
||||
#define PLL3000_SDIV_SHIFT (0)
|
||||
|
||||
static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 pll_con, mdiv, pdiv, sdiv;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
|
||||
sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
|
||||
|
||||
fvco *= (2 * (mdiv + 8));
|
||||
do_div(fvco, pdiv << sdiv);
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll3000_clk_ops = {
|
||||
.recalc_rate = samsung_pll3000_recalc_rate,
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL35xx Clock Type
|
||||
*/
|
||||
@ -564,7 +631,9 @@ static const struct clk_ops samsung_pll46xx_clk_min_ops = {
|
||||
#define PLL6552_PDIV_MASK 0x3f
|
||||
#define PLL6552_SDIV_MASK 0x7
|
||||
#define PLL6552_MDIV_SHIFT 16
|
||||
#define PLL6552_MDIV_SHIFT_2416 14
|
||||
#define PLL6552_PDIV_SHIFT 8
|
||||
#define PLL6552_PDIV_SHIFT_2416 5
|
||||
#define PLL6552_SDIV_SHIFT 0
|
||||
|
||||
static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
|
||||
@ -575,8 +644,13 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
|
||||
if (pll->type == pll_6552_s3c2416) {
|
||||
mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
|
||||
} else {
|
||||
mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
|
||||
}
|
||||
sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
|
||||
|
||||
fvco *= mdiv;
|
||||
@ -627,6 +701,169 @@ static const struct clk_ops samsung_pll6553_clk_ops = {
|
||||
.recalc_rate = samsung_pll6553_recalc_rate,
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL Clock Type of S3C24XX before S3C2443
|
||||
*/
|
||||
|
||||
#define PLLS3C2410_MDIV_MASK (0xff)
|
||||
#define PLLS3C2410_PDIV_MASK (0x1f)
|
||||
#define PLLS3C2410_SDIV_MASK (0x3)
|
||||
#define PLLS3C2410_MDIV_SHIFT (12)
|
||||
#define PLLS3C2410_PDIV_SHIFT (4)
|
||||
#define PLLS3C2410_SDIV_SHIFT (0)
|
||||
|
||||
#define PLLS3C2410_ENABLE_REG_OFFSET 0x10
|
||||
|
||||
static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 pll_con, mdiv, pdiv, sdiv;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
|
||||
sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
|
||||
|
||||
fvco *= (mdiv + 8);
|
||||
do_div(fvco, (pdiv + 2) << sdiv);
|
||||
|
||||
return (unsigned int)fvco;
|
||||
}
|
||||
|
||||
static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 pll_con, mdiv, pdiv, sdiv;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
|
||||
sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
|
||||
|
||||
fvco *= (2 * (mdiv + 8));
|
||||
do_div(fvco, (pdiv + 2) << sdiv);
|
||||
|
||||
return (unsigned int)fvco;
|
||||
}
|
||||
|
||||
static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
const struct samsung_pll_rate_table *rate;
|
||||
u32 tmp;
|
||||
|
||||
/* Get required rate settings from table */
|
||||
rate = samsung_get_pll_settings(pll, drate);
|
||||
if (!rate) {
|
||||
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
|
||||
drate, __clk_get_name(hw->clk));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = __raw_readl(pll->con_reg);
|
||||
|
||||
/* Change PLL PMS values */
|
||||
tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
|
||||
(PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) |
|
||||
(PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT));
|
||||
tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
|
||||
(rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
|
||||
(rate->sdiv << PLLS3C2410_SDIV_SHIFT);
|
||||
__raw_writel(tmp, pll->con_reg);
|
||||
|
||||
/* Time to settle according to the manual */
|
||||
udelay(300);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
|
||||
{
|
||||
struct samsung_clk_pll *pll = to_clk_pll(hw);
|
||||
u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
|
||||
u32 pll_en_orig = pll_en;
|
||||
|
||||
if (enable)
|
||||
pll_en &= ~BIT(bit);
|
||||
else
|
||||
pll_en |= BIT(bit);
|
||||
|
||||
__raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
|
||||
|
||||
/* if we started the UPLL, then allow to settle */
|
||||
if (enable && (pll_en_orig & BIT(bit)))
|
||||
udelay(300);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
|
||||
{
|
||||
return samsung_s3c2410_pll_enable(hw, 5, true);
|
||||
}
|
||||
|
||||
static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
|
||||
{
|
||||
samsung_s3c2410_pll_enable(hw, 5, false);
|
||||
}
|
||||
|
||||
static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
|
||||
{
|
||||
return samsung_s3c2410_pll_enable(hw, 7, true);
|
||||
}
|
||||
|
||||
static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
|
||||
{
|
||||
samsung_s3c2410_pll_enable(hw, 7, false);
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = {
|
||||
.recalc_rate = samsung_s3c2410_pll_recalc_rate,
|
||||
.enable = samsung_s3c2410_mpll_enable,
|
||||
.disable = samsung_s3c2410_mpll_disable,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = {
|
||||
.recalc_rate = samsung_s3c2410_pll_recalc_rate,
|
||||
.enable = samsung_s3c2410_upll_enable,
|
||||
.disable = samsung_s3c2410_upll_disable,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = {
|
||||
.recalc_rate = samsung_s3c2440_mpll_recalc_rate,
|
||||
.enable = samsung_s3c2410_mpll_enable,
|
||||
.disable = samsung_s3c2410_mpll_disable,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_s3c2410_mpll_clk_ops = {
|
||||
.recalc_rate = samsung_s3c2410_pll_recalc_rate,
|
||||
.enable = samsung_s3c2410_mpll_enable,
|
||||
.disable = samsung_s3c2410_mpll_disable,
|
||||
.round_rate = samsung_pll_round_rate,
|
||||
.set_rate = samsung_s3c2410_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_s3c2410_upll_clk_ops = {
|
||||
.recalc_rate = samsung_s3c2410_pll_recalc_rate,
|
||||
.enable = samsung_s3c2410_upll_enable,
|
||||
.disable = samsung_s3c2410_upll_disable,
|
||||
.round_rate = samsung_pll_round_rate,
|
||||
.set_rate = samsung_s3c2410_pll_set_rate,
|
||||
};
|
||||
|
||||
static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
|
||||
.recalc_rate = samsung_s3c2440_mpll_recalc_rate,
|
||||
.enable = samsung_s3c2410_mpll_enable,
|
||||
.disable = samsung_s3c2410_mpll_disable,
|
||||
.round_rate = samsung_pll_round_rate,
|
||||
.set_rate = samsung_s3c2410_pll_set_rate,
|
||||
};
|
||||
|
||||
/*
|
||||
* PLL2550x Clock Type
|
||||
*/
|
||||
@ -746,6 +983,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
|
||||
}
|
||||
|
||||
switch (pll_clk->type) {
|
||||
case pll_2126:
|
||||
init.ops = &samsung_pll2126_clk_ops;
|
||||
break;
|
||||
case pll_3000:
|
||||
init.ops = &samsung_pll3000_clk_ops;
|
||||
break;
|
||||
/* clk_ops for 35xx and 2550 are similar */
|
||||
case pll_35xx:
|
||||
case pll_2550:
|
||||
@ -773,6 +1016,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
|
||||
init.ops = &samsung_pll36xx_clk_ops;
|
||||
break;
|
||||
case pll_6552:
|
||||
case pll_6552_s3c2416:
|
||||
init.ops = &samsung_pll6552_clk_ops;
|
||||
break;
|
||||
case pll_6553:
|
||||
@ -786,6 +1030,24 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
|
||||
else
|
||||
init.ops = &samsung_pll46xx_clk_ops;
|
||||
break;
|
||||
case pll_s3c2410_mpll:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_s3c2410_mpll_clk_min_ops;
|
||||
else
|
||||
init.ops = &samsung_s3c2410_mpll_clk_ops;
|
||||
break;
|
||||
case pll_s3c2410_upll:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_s3c2410_upll_clk_min_ops;
|
||||
else
|
||||
init.ops = &samsung_s3c2410_upll_clk_ops;
|
||||
break;
|
||||
case pll_s3c2440_mpll:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &samsung_s3c2440_mpll_clk_min_ops;
|
||||
else
|
||||
init.ops = &samsung_s3c2440_mpll_clk_ops;
|
||||
break;
|
||||
default:
|
||||
pr_warn("%s: Unknown pll type for pll clk %s\n",
|
||||
__func__, pll_clk->name);
|
||||
|
@ -13,6 +13,8 @@
|
||||
#define __SAMSUNG_CLK_PLL_H
|
||||
|
||||
enum samsung_pll_type {
|
||||
pll_2126,
|
||||
pll_3000,
|
||||
pll_35xx,
|
||||
pll_36xx,
|
||||
pll_2550,
|
||||
@ -24,7 +26,11 @@ enum samsung_pll_type {
|
||||
pll_4650,
|
||||
pll_4650c,
|
||||
pll_6552,
|
||||
pll_6552_s3c2416,
|
||||
pll_6553,
|
||||
pll_s3c2410_mpll,
|
||||
pll_s3c2410_upll,
|
||||
pll_s3c2440_mpll,
|
||||
};
|
||||
|
||||
#define PLL_35XX_RATE(_rate, _m, _p, _s) \
|
||||
|
440
drivers/clk/samsung/clk-s3c2410-dclk.c
Normal file
440
drivers/clk/samsung/clk-s3c2410-dclk.c
Normal file
@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for s3c24xx external clock output.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include "clk.h"
|
||||
|
||||
/* legacy access to misccr, until dt conversion is finished */
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/regs-gpio.h>
|
||||
|
||||
#define MUX_DCLK0 0
|
||||
#define MUX_DCLK1 1
|
||||
#define DIV_DCLK0 2
|
||||
#define DIV_DCLK1 3
|
||||
#define GATE_DCLK0 4
|
||||
#define GATE_DCLK1 5
|
||||
#define MUX_CLKOUT0 6
|
||||
#define MUX_CLKOUT1 7
|
||||
#define DCLK_MAX_CLKS (MUX_CLKOUT1 + 1)
|
||||
|
||||
enum supported_socs {
|
||||
S3C2410,
|
||||
S3C2412,
|
||||
S3C2440,
|
||||
S3C2443,
|
||||
};
|
||||
|
||||
struct s3c24xx_dclk_drv_data {
|
||||
const char **clkout0_parent_names;
|
||||
int clkout0_num_parents;
|
||||
const char **clkout1_parent_names;
|
||||
int clkout1_num_parents;
|
||||
const char **mux_parent_names;
|
||||
int mux_num_parents;
|
||||
};
|
||||
|
||||
/*
|
||||
* Clock for output-parent selection in misccr
|
||||
*/
|
||||
|
||||
struct s3c24xx_clkout {
|
||||
struct clk_hw hw;
|
||||
u32 mask;
|
||||
u8 shift;
|
||||
};
|
||||
|
||||
#define to_s3c24xx_clkout(_hw) container_of(_hw, struct s3c24xx_clkout, hw)
|
||||
|
||||
static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
|
||||
int num_parents = __clk_get_num_parents(hw->clk);
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift;
|
||||
val >>= clkout->shift;
|
||||
val &= clkout->mask;
|
||||
|
||||
if (val >= num_parents)
|
||||
return -EINVAL;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
|
||||
int ret = 0;
|
||||
|
||||
s3c2410_modify_misccr((clkout->mask << clkout->shift),
|
||||
(index << clkout->shift));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct clk_ops s3c24xx_clkout_ops = {
|
||||
.get_parent = s3c24xx_clkout_get_parent,
|
||||
.set_parent = s3c24xx_clkout_set_parent,
|
||||
.determine_rate = __clk_mux_determine_rate,
|
||||
};
|
||||
|
||||
struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
|
||||
const char **parent_names, u8 num_parents,
|
||||
u8 shift, u32 mask)
|
||||
{
|
||||
struct s3c24xx_clkout *clkout;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init;
|
||||
|
||||
/* allocate the clkout */
|
||||
clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
|
||||
if (!clkout)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &s3c24xx_clkout_ops;
|
||||
init.flags = CLK_IS_BASIC;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
|
||||
clkout->shift = shift;
|
||||
clkout->mask = mask;
|
||||
clkout->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &clkout->hw);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* dclk and clkout init
|
||||
*/
|
||||
|
||||
struct s3c24xx_dclk {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct clk_onecell_data clk_data;
|
||||
struct notifier_block dclk0_div_change_nb;
|
||||
struct notifier_block dclk1_div_change_nb;
|
||||
spinlock_t dclk_lock;
|
||||
unsigned long reg_save;
|
||||
};
|
||||
|
||||
#define to_s3c24xx_dclk0(x) \
|
||||
container_of(x, struct s3c24xx_dclk, dclk0_div_change_nb)
|
||||
|
||||
#define to_s3c24xx_dclk1(x) \
|
||||
container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb)
|
||||
|
||||
PNAME(dclk_s3c2410_p) = { "pclk", "uclk" };
|
||||
PNAME(clkout0_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk",
|
||||
"gate_dclk0" };
|
||||
PNAME(clkout1_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk",
|
||||
"gate_dclk1" };
|
||||
|
||||
PNAME(clkout0_s3c2412_p) = { "mpll", "upll", "rtc_clkout",
|
||||
"hclk", "pclk", "gate_dclk0" };
|
||||
PNAME(clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk",
|
||||
"gate_dclk1" };
|
||||
|
||||
PNAME(clkout0_s3c2440_p) = { "xti", "upll", "fclk", "hclk", "pclk",
|
||||
"gate_dclk0" };
|
||||
PNAME(clkout1_s3c2440_p) = { "mpll", "upll", "rtc_clkout",
|
||||
"hclk", "pclk", "gate_dclk1" };
|
||||
|
||||
PNAME(dclk_s3c2443_p) = { "pclk", "epll" };
|
||||
PNAME(clkout0_s3c2443_p) = { "xti", "epll", "armclk", "hclk", "pclk",
|
||||
"gate_dclk0" };
|
||||
PNAME(clkout1_s3c2443_p) = { "dummy", "epll", "rtc_clkout",
|
||||
"hclk", "pclk", "gate_dclk1" };
|
||||
|
||||
#define DCLKCON_DCLK_DIV_MASK 0xf
|
||||
#define DCLKCON_DCLK0_DIV_SHIFT 4
|
||||
#define DCLKCON_DCLK0_CMP_SHIFT 8
|
||||
#define DCLKCON_DCLK1_DIV_SHIFT 20
|
||||
#define DCLKCON_DCLK1_CMP_SHIFT 24
|
||||
|
||||
static void s3c24xx_dclk_update_cmp(struct s3c24xx_dclk *s3c24xx_dclk,
|
||||
int div_shift, int cmp_shift)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
u32 dclk_con, div, cmp;
|
||||
|
||||
spin_lock_irqsave(&s3c24xx_dclk->dclk_lock, flags);
|
||||
|
||||
dclk_con = readl_relaxed(s3c24xx_dclk->base);
|
||||
|
||||
div = ((dclk_con >> div_shift) & DCLKCON_DCLK_DIV_MASK) + 1;
|
||||
cmp = ((div + 1) / 2) - 1;
|
||||
|
||||
dclk_con &= ~(DCLKCON_DCLK_DIV_MASK << cmp_shift);
|
||||
dclk_con |= (cmp << cmp_shift);
|
||||
|
||||
writel_relaxed(dclk_con, s3c24xx_dclk->base);
|
||||
|
||||
spin_unlock_irqrestore(&s3c24xx_dclk->dclk_lock, flags);
|
||||
}
|
||||
|
||||
static int s3c24xx_dclk0_div_notify(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk0(nb);
|
||||
|
||||
if (event == POST_RATE_CHANGE) {
|
||||
s3c24xx_dclk_update_cmp(s3c24xx_dclk,
|
||||
DCLKCON_DCLK0_DIV_SHIFT, DCLKCON_DCLK0_CMP_SHIFT);
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int s3c24xx_dclk1_div_notify(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk1(nb);
|
||||
|
||||
if (event == POST_RATE_CHANGE) {
|
||||
s3c24xx_dclk_update_cmp(s3c24xx_dclk,
|
||||
DCLKCON_DCLK1_DIV_SHIFT, DCLKCON_DCLK1_CMP_SHIFT);
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int s3c24xx_dclk_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
|
||||
|
||||
s3c24xx_dclk->reg_save = readl_relaxed(s3c24xx_dclk->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c24xx_dclk_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
|
||||
|
||||
writel_relaxed(s3c24xx_dclk->reg_save, s3c24xx_dclk->base);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops,
|
||||
s3c24xx_dclk_suspend, s3c24xx_dclk_resume);
|
||||
|
||||
static int s3c24xx_dclk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct s3c24xx_dclk *s3c24xx_dclk;
|
||||
struct resource *mem;
|
||||
struct clk **clk_table;
|
||||
struct s3c24xx_dclk_drv_data *dclk_variant;
|
||||
int ret, i;
|
||||
|
||||
s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk),
|
||||
GFP_KERNEL);
|
||||
if (!s3c24xx_dclk)
|
||||
return -ENOMEM;
|
||||
|
||||
s3c24xx_dclk->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, s3c24xx_dclk);
|
||||
spin_lock_init(&s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct clk *) * DCLK_MAX_CLKS,
|
||||
GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
return -ENOMEM;
|
||||
|
||||
s3c24xx_dclk->clk_data.clks = clk_table;
|
||||
s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
if (IS_ERR(s3c24xx_dclk->base))
|
||||
return PTR_ERR(s3c24xx_dclk->base);
|
||||
|
||||
dclk_variant = (struct s3c24xx_dclk_drv_data *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
|
||||
|
||||
clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0",
|
||||
dclk_variant->mux_parent_names,
|
||||
dclk_variant->mux_num_parents, 0,
|
||||
s3c24xx_dclk->base, 1, 1, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1",
|
||||
dclk_variant->mux_parent_names,
|
||||
dclk_variant->mux_num_parents, 0,
|
||||
s3c24xx_dclk->base, 17, 1, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0",
|
||||
"mux_dclk0", 0, s3c24xx_dclk->base,
|
||||
4, 4, 0, &s3c24xx_dclk->dclk_lock);
|
||||
clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1",
|
||||
"mux_dclk1", 0, s3c24xx_dclk->base,
|
||||
20, 4, 0, &s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0",
|
||||
"div_dclk0", CLK_SET_RATE_PARENT,
|
||||
s3c24xx_dclk->base, 0, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1",
|
||||
"div_dclk1", CLK_SET_RATE_PARENT,
|
||||
s3c24xx_dclk->base, 16, 0,
|
||||
&s3c24xx_dclk->dclk_lock);
|
||||
|
||||
clk_table[MUX_CLKOUT0] = s3c24xx_register_clkout(&pdev->dev,
|
||||
"clkout0", dclk_variant->clkout0_parent_names,
|
||||
dclk_variant->clkout0_num_parents, 4, 7);
|
||||
clk_table[MUX_CLKOUT1] = s3c24xx_register_clkout(&pdev->dev,
|
||||
"clkout1", dclk_variant->clkout1_parent_names,
|
||||
dclk_variant->clkout1_num_parents, 8, 7);
|
||||
|
||||
for (i = 0; i < DCLK_MAX_CLKS; i++)
|
||||
if (IS_ERR(clk_table[i])) {
|
||||
dev_err(&pdev->dev, "clock %d failed to register\n", i);
|
||||
ret = PTR_ERR(clk_table[i]);
|
||||
goto err_clk_register;
|
||||
}
|
||||
|
||||
ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL);
|
||||
if (!ret)
|
||||
ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL);
|
||||
if (!ret)
|
||||
ret = clk_register_clkdev(clk_table[MUX_CLKOUT0],
|
||||
"clkout0", NULL);
|
||||
if (!ret)
|
||||
ret = clk_register_clkdev(clk_table[MUX_CLKOUT1],
|
||||
"clkout1", NULL);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register aliases, %d\n", ret);
|
||||
goto err_clk_register;
|
||||
}
|
||||
|
||||
s3c24xx_dclk->dclk0_div_change_nb.notifier_call =
|
||||
s3c24xx_dclk0_div_notify;
|
||||
|
||||
s3c24xx_dclk->dclk1_div_change_nb.notifier_call =
|
||||
s3c24xx_dclk1_div_notify;
|
||||
|
||||
ret = clk_notifier_register(clk_table[DIV_DCLK0],
|
||||
&s3c24xx_dclk->dclk0_div_change_nb);
|
||||
if (ret)
|
||||
goto err_clk_register;
|
||||
|
||||
ret = clk_notifier_register(clk_table[DIV_DCLK1],
|
||||
&s3c24xx_dclk->dclk1_div_change_nb);
|
||||
if (ret)
|
||||
goto err_dclk_notify;
|
||||
|
||||
return 0;
|
||||
|
||||
err_dclk_notify:
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK0],
|
||||
&s3c24xx_dclk->dclk0_div_change_nb);
|
||||
err_clk_register:
|
||||
for (i = 0; i < DCLK_MAX_CLKS; i++)
|
||||
if (clk_table[i] && !IS_ERR(clk_table[i]))
|
||||
clk_unregister(clk_table[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s3c24xx_dclk_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev);
|
||||
struct clk **clk_table = s3c24xx_dclk->clk_data.clks;
|
||||
int i;
|
||||
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK1],
|
||||
&s3c24xx_dclk->dclk1_div_change_nb);
|
||||
clk_notifier_unregister(clk_table[DIV_DCLK0],
|
||||
&s3c24xx_dclk->dclk0_div_change_nb);
|
||||
|
||||
for (i = 0; i < DCLK_MAX_CLKS; i++)
|
||||
clk_unregister(clk_table[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s3c24xx_dclk_drv_data dclk_variants[] = {
|
||||
[S3C2410] = {
|
||||
.clkout0_parent_names = clkout0_s3c2410_p,
|
||||
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2410_p),
|
||||
.clkout1_parent_names = clkout1_s3c2410_p,
|
||||
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2410_p),
|
||||
.mux_parent_names = dclk_s3c2410_p,
|
||||
.mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
|
||||
},
|
||||
[S3C2412] = {
|
||||
.clkout0_parent_names = clkout0_s3c2412_p,
|
||||
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2412_p),
|
||||
.clkout1_parent_names = clkout1_s3c2412_p,
|
||||
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2412_p),
|
||||
.mux_parent_names = dclk_s3c2410_p,
|
||||
.mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
|
||||
},
|
||||
[S3C2440] = {
|
||||
.clkout0_parent_names = clkout0_s3c2440_p,
|
||||
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2440_p),
|
||||
.clkout1_parent_names = clkout1_s3c2440_p,
|
||||
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2440_p),
|
||||
.mux_parent_names = dclk_s3c2410_p,
|
||||
.mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p),
|
||||
},
|
||||
[S3C2443] = {
|
||||
.clkout0_parent_names = clkout0_s3c2443_p,
|
||||
.clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2443_p),
|
||||
.clkout1_parent_names = clkout1_s3c2443_p,
|
||||
.clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2443_p),
|
||||
.mux_parent_names = dclk_s3c2443_p,
|
||||
.mux_num_parents = ARRAY_SIZE(dclk_s3c2443_p),
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
|
||||
{
|
||||
.name = "s3c2410-dclk",
|
||||
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2410],
|
||||
}, {
|
||||
.name = "s3c2412-dclk",
|
||||
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2412],
|
||||
}, {
|
||||
.name = "s3c2440-dclk",
|
||||
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2440],
|
||||
}, {
|
||||
.name = "s3c2443-dclk",
|
||||
.driver_data = (kernel_ulong_t)&dclk_variants[S3C2443],
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
|
||||
|
||||
static struct platform_driver s3c24xx_dclk_driver = {
|
||||
.driver = {
|
||||
.name = "s3c24xx-dclk",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &s3c24xx_dclk_pm_ops,
|
||||
},
|
||||
.probe = s3c24xx_dclk_probe,
|
||||
.remove = s3c24xx_dclk_remove,
|
||||
.id_table = s3c24xx_dclk_driver_ids,
|
||||
};
|
||||
module_platform_driver(s3c24xx_dclk_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
|
||||
MODULE_DESCRIPTION("Driver for the S3C24XX external clock outputs");
|
477
drivers/clk/samsung/clk-s3c2410.c
Normal file
477
drivers/clk/samsung/clk-s3c2410.c
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for S3C2410 and following SoCs.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <dt-bindings/clock/s3c2410.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
#define LOCKTIME 0x00
|
||||
#define MPLLCON 0x04
|
||||
#define UPLLCON 0x08
|
||||
#define CLKCON 0x0c
|
||||
#define CLKSLOW 0x10
|
||||
#define CLKDIVN 0x14
|
||||
#define CAMDIVN 0x18
|
||||
|
||||
/* the soc types */
|
||||
enum supported_socs {
|
||||
S3C2410,
|
||||
S3C2440,
|
||||
S3C2442,
|
||||
};
|
||||
|
||||
/* list of PLLs to be registered */
|
||||
enum s3c2410_plls {
|
||||
mpll, upll,
|
||||
};
|
||||
|
||||
static void __iomem *reg_base;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static struct samsung_clk_reg_dump *s3c2410_save;
|
||||
|
||||
/*
|
||||
* list of controller registers to be saved and restored during a
|
||||
* suspend/resume cycle.
|
||||
*/
|
||||
static unsigned long s3c2410_clk_regs[] __initdata = {
|
||||
LOCKTIME,
|
||||
MPLLCON,
|
||||
UPLLCON,
|
||||
CLKCON,
|
||||
CLKSLOW,
|
||||
CLKDIVN,
|
||||
CAMDIVN,
|
||||
};
|
||||
|
||||
static int s3c2410_clk_suspend(void)
|
||||
{
|
||||
samsung_clk_save(reg_base, s3c2410_save,
|
||||
ARRAY_SIZE(s3c2410_clk_regs));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c2410_clk_resume(void)
|
||||
{
|
||||
samsung_clk_restore(reg_base, s3c2410_save,
|
||||
ARRAY_SIZE(s3c2410_clk_regs));
|
||||
}
|
||||
|
||||
static struct syscore_ops s3c2410_clk_syscore_ops = {
|
||||
.suspend = s3c2410_clk_suspend,
|
||||
.resume = s3c2410_clk_resume,
|
||||
};
|
||||
|
||||
static void s3c2410_clk_sleep_init(void)
|
||||
{
|
||||
s3c2410_save = samsung_clk_alloc_reg_dump(s3c2410_clk_regs,
|
||||
ARRAY_SIZE(s3c2410_clk_regs));
|
||||
if (!s3c2410_save) {
|
||||
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
register_syscore_ops(&s3c2410_clk_syscore_ops);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static void s3c2410_clk_sleep_init(void) {}
|
||||
#endif
|
||||
|
||||
PNAME(fclk_p) = { "mpll", "div_slow" };
|
||||
|
||||
struct samsung_mux_clock s3c2410_common_muxes[] __initdata = {
|
||||
MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1),
|
||||
};
|
||||
|
||||
static struct clk_div_table divslow_d[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 1, .div = 2 },
|
||||
{ .val = 2, .div = 4 },
|
||||
{ .val = 3, .div = 6 },
|
||||
{ .val = 4, .div = 8 },
|
||||
{ .val = 5, .div = 10 },
|
||||
{ .val = 6, .div = 12 },
|
||||
{ .val = 7, .div = 14 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c2410_common_dividers[] __initdata = {
|
||||
DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d),
|
||||
DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2410_common_gates[] __initdata = {
|
||||
GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0),
|
||||
GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0),
|
||||
GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0),
|
||||
GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0),
|
||||
GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0),
|
||||
GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0),
|
||||
GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0),
|
||||
GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0),
|
||||
GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0),
|
||||
GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0),
|
||||
GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0),
|
||||
GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
|
||||
GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
|
||||
GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
|
||||
};
|
||||
|
||||
/* should be added _after_ the soc-specific clocks are created */
|
||||
struct samsung_clock_alias s3c2410_common_aliases[] __initdata = {
|
||||
ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
|
||||
ALIAS(PCLK_ADC, NULL, "adc"),
|
||||
ALIAS(PCLK_RTC, NULL, "rtc"),
|
||||
ALIAS(PCLK_PWM, NULL, "timers"),
|
||||
ALIAS(HCLK_LCD, NULL, "lcd"),
|
||||
ALIAS(HCLK_USBD, NULL, "usb-device"),
|
||||
ALIAS(HCLK_USBH, NULL, "usb-host"),
|
||||
ALIAS(UCLK, NULL, "usb-bus-host"),
|
||||
ALIAS(UCLK, NULL, "usb-bus-gadget"),
|
||||
ALIAS(ARMCLK, NULL, "armclk"),
|
||||
ALIAS(UCLK, NULL, "uclk"),
|
||||
ALIAS(HCLK, NULL, "hclk"),
|
||||
ALIAS(MPLL, NULL, "mpll"),
|
||||
ALIAS(FCLK, NULL, "fclk"),
|
||||
};
|
||||
|
||||
/* S3C2410 specific clocks */
|
||||
|
||||
static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
|
||||
/* sorted in descending order */
|
||||
/* 2410A extras */
|
||||
PLL_35XX_RATE(270000000, 127, 1, 1),
|
||||
PLL_35XX_RATE(268000000, 126, 1, 1),
|
||||
PLL_35XX_RATE(266000000, 125, 1, 1),
|
||||
PLL_35XX_RATE(226000000, 105, 1, 1),
|
||||
PLL_35XX_RATE(210000000, 132, 2, 1),
|
||||
/* 2410 common */
|
||||
PLL_35XX_RATE(203000000, 161, 3, 1),
|
||||
PLL_35XX_RATE(192000000, 88, 1, 1),
|
||||
PLL_35XX_RATE(186000000, 85, 1, 1),
|
||||
PLL_35XX_RATE(180000000, 82, 1, 1),
|
||||
PLL_35XX_RATE(170000000, 77, 1, 1),
|
||||
PLL_35XX_RATE(158000000, 71, 1, 1),
|
||||
PLL_35XX_RATE(152000000, 68, 1, 1),
|
||||
PLL_35XX_RATE(147000000, 90, 2, 1),
|
||||
PLL_35XX_RATE(135000000, 82, 2, 1),
|
||||
PLL_35XX_RATE(124000000, 116, 1, 2),
|
||||
PLL_35XX_RATE(118000000, 150, 2, 2),
|
||||
PLL_35XX_RATE(113000000, 105, 1, 2),
|
||||
PLL_35XX_RATE(101000000, 127, 2, 2),
|
||||
PLL_35XX_RATE(90000000, 112, 2, 2),
|
||||
PLL_35XX_RATE(85000000, 105, 2, 2),
|
||||
PLL_35XX_RATE(79000000, 71, 1, 2),
|
||||
PLL_35XX_RATE(68000000, 82, 2, 2),
|
||||
PLL_35XX_RATE(56000000, 142, 2, 3),
|
||||
PLL_35XX_RATE(48000000, 120, 2, 3),
|
||||
PLL_35XX_RATE(51000000, 161, 3, 3),
|
||||
PLL_35XX_RATE(45000000, 82, 1, 3),
|
||||
PLL_35XX_RATE(34000000, 82, 2, 3),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct samsung_pll_clock s3c2410_plls[] __initdata = {
|
||||
[mpll] = PLL(pll_s3c2410_mpll, MPLL, "mpll", "xti",
|
||||
LOCKTIME, MPLLCON, NULL),
|
||||
[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti",
|
||||
LOCKTIME, UPLLCON, NULL),
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c2410_dividers[] __initdata = {
|
||||
DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1),
|
||||
};
|
||||
|
||||
struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = {
|
||||
/*
|
||||
* armclk is directly supplied by the fclk, without
|
||||
* switching possibility like on the s3c244x below.
|
||||
*/
|
||||
FFACTOR(ARMCLK, "armclk", "fclk", 1, 1, 0),
|
||||
|
||||
/* uclk is fed from the unmodified upll */
|
||||
FFACTOR(UCLK, "uclk", "upll", 1, 1, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c2410_aliases[] __initdata = {
|
||||
ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"),
|
||||
ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"),
|
||||
ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"),
|
||||
ALIAS(PCLK_UART0, "s3c2410-uart.0", "clk_uart_baud0"),
|
||||
ALIAS(PCLK_UART1, "s3c2410-uart.1", "clk_uart_baud0"),
|
||||
ALIAS(PCLK_UART2, "s3c2410-uart.2", "clk_uart_baud0"),
|
||||
ALIAS(UCLK, NULL, "clk_uart_baud1"),
|
||||
};
|
||||
|
||||
/* S3C244x specific clocks */
|
||||
|
||||
static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = {
|
||||
/* sorted in descending order */
|
||||
PLL_35XX_RATE(400000000, 0x5c, 1, 1),
|
||||
PLL_35XX_RATE(390000000, 0x7a, 2, 1),
|
||||
PLL_35XX_RATE(380000000, 0x57, 1, 1),
|
||||
PLL_35XX_RATE(370000000, 0xb1, 4, 1),
|
||||
PLL_35XX_RATE(360000000, 0x70, 2, 1),
|
||||
PLL_35XX_RATE(350000000, 0xa7, 4, 1),
|
||||
PLL_35XX_RATE(340000000, 0x4d, 1, 1),
|
||||
PLL_35XX_RATE(330000000, 0x66, 2, 1),
|
||||
PLL_35XX_RATE(320000000, 0x98, 4, 1),
|
||||
PLL_35XX_RATE(310000000, 0x93, 4, 1),
|
||||
PLL_35XX_RATE(300000000, 0x75, 3, 1),
|
||||
PLL_35XX_RATE(240000000, 0x70, 1, 2),
|
||||
PLL_35XX_RATE(230000000, 0x6b, 1, 2),
|
||||
PLL_35XX_RATE(220000000, 0x66, 1, 2),
|
||||
PLL_35XX_RATE(210000000, 0x84, 2, 2),
|
||||
PLL_35XX_RATE(200000000, 0x5c, 1, 2),
|
||||
PLL_35XX_RATE(190000000, 0x57, 1, 2),
|
||||
PLL_35XX_RATE(180000000, 0x70, 2, 2),
|
||||
PLL_35XX_RATE(170000000, 0x4d, 1, 2),
|
||||
PLL_35XX_RATE(160000000, 0x98, 4, 2),
|
||||
PLL_35XX_RATE(150000000, 0x75, 3, 2),
|
||||
PLL_35XX_RATE(120000000, 0x70, 1, 3),
|
||||
PLL_35XX_RATE(110000000, 0x66, 1, 3),
|
||||
PLL_35XX_RATE(100000000, 0x5c, 1, 3),
|
||||
PLL_35XX_RATE(90000000, 0x70, 2, 3),
|
||||
PLL_35XX_RATE(80000000, 0x98, 4, 3),
|
||||
PLL_35XX_RATE(75000000, 0x75, 3, 3),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct samsung_pll_clock s3c244x_common_plls[] __initdata = {
|
||||
[mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
|
||||
LOCKTIME, MPLLCON, NULL),
|
||||
[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti",
|
||||
LOCKTIME, UPLLCON, NULL),
|
||||
};
|
||||
|
||||
PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" };
|
||||
PNAME(armclk_p) = { "fclk", "hclk" };
|
||||
|
||||
struct samsung_mux_clock s3c244x_common_muxes[] __initdata = {
|
||||
MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2),
|
||||
MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1),
|
||||
};
|
||||
|
||||
struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = {
|
||||
FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0),
|
||||
FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT),
|
||||
};
|
||||
|
||||
static struct clk_div_table div_hclk_4_d[] = {
|
||||
{ .val = 0, .div = 4 },
|
||||
{ .val = 1, .div = 8 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct clk_div_table div_hclk_3_d[] = {
|
||||
{ .val = 0, .div = 3 },
|
||||
{ .val = 1, .div = 6 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c244x_common_dividers[] __initdata = {
|
||||
DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1),
|
||||
DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1),
|
||||
DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d),
|
||||
DIV_T(0, "div_hclk_3", "fclk", CAMDIVN, 8, 1, div_hclk_3_d),
|
||||
DIV(0, "div_cam", "upll", CAMDIVN, 0, 3),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c244x_common_gates[] __initdata = {
|
||||
GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c244x_common_aliases[] __initdata = {
|
||||
ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
|
||||
ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
|
||||
ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
|
||||
ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
|
||||
ALIAS(HCLK_CAM, NULL, "camif"),
|
||||
ALIAS(CAMIF, NULL, "camif-upll"),
|
||||
};
|
||||
|
||||
/* S3C2440 specific clocks */
|
||||
|
||||
PNAME(s3c2440_camif_p) = { "upll", "ff_cam" };
|
||||
|
||||
struct samsung_mux_clock s3c2440_muxes[] __initdata = {
|
||||
MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2440_gates[] __initdata = {
|
||||
GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0),
|
||||
};
|
||||
|
||||
/* S3C2442 specific clocks */
|
||||
|
||||
struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = {
|
||||
FFACTOR(0, "upll_3", "upll", 1, 3, 0),
|
||||
};
|
||||
|
||||
PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" };
|
||||
|
||||
struct samsung_mux_clock s3c2442_muxes[] __initdata = {
|
||||
MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2),
|
||||
};
|
||||
|
||||
/*
|
||||
* fixed rate clocks generated outside the soc
|
||||
* Only necessary until the devicetree-move is complete
|
||||
*/
|
||||
#define XTI 1
|
||||
struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = {
|
||||
FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
|
||||
};
|
||||
|
||||
static void __init s3c2410_common_clk_register_fixed_ext(unsigned long xti_f)
|
||||
{
|
||||
struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
|
||||
|
||||
s3c2410_common_frate_clks[0].fixed_rate = xti_f;
|
||||
samsung_clk_register_fixed_rate(s3c2410_common_frate_clks,
|
||||
ARRAY_SIZE(s3c2410_common_frate_clks));
|
||||
|
||||
samsung_clk_register_alias(&xti_alias, 1);
|
||||
}
|
||||
|
||||
void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
int current_soc,
|
||||
void __iomem *base)
|
||||
{
|
||||
reg_base = base;
|
||||
|
||||
if (np) {
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
}
|
||||
|
||||
samsung_clk_init(np, reg_base, NR_CLKS);
|
||||
|
||||
/* Register external clocks only in non-dt cases */
|
||||
if (!np)
|
||||
s3c2410_common_clk_register_fixed_ext(xti_f);
|
||||
|
||||
if (current_soc == 2410) {
|
||||
if (_get_rate("xti") == 12 * MHZ) {
|
||||
s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl;
|
||||
s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl;
|
||||
}
|
||||
|
||||
/* Register PLLs. */
|
||||
samsung_clk_register_pll(s3c2410_plls,
|
||||
ARRAY_SIZE(s3c2410_plls), reg_base);
|
||||
|
||||
} else { /* S3C2440, S3C2442 */
|
||||
if (_get_rate("xti") == 12 * MHZ) {
|
||||
/*
|
||||
* plls follow different calculation schemes, with the
|
||||
* upll following the same scheme as the s3c2410 plls
|
||||
*/
|
||||
s3c244x_common_plls[mpll].rate_table =
|
||||
pll_s3c244x_12mhz_tbl;
|
||||
s3c244x_common_plls[upll].rate_table =
|
||||
pll_s3c2410_12mhz_tbl;
|
||||
}
|
||||
|
||||
/* Register PLLs. */
|
||||
samsung_clk_register_pll(s3c244x_common_plls,
|
||||
ARRAY_SIZE(s3c244x_common_plls), reg_base);
|
||||
}
|
||||
|
||||
/* Register common internal clocks. */
|
||||
samsung_clk_register_mux(s3c2410_common_muxes,
|
||||
ARRAY_SIZE(s3c2410_common_muxes));
|
||||
samsung_clk_register_div(s3c2410_common_dividers,
|
||||
ARRAY_SIZE(s3c2410_common_dividers));
|
||||
samsung_clk_register_gate(s3c2410_common_gates,
|
||||
ARRAY_SIZE(s3c2410_common_gates));
|
||||
|
||||
if (current_soc == S3C2440 || current_soc == S3C2442) {
|
||||
samsung_clk_register_div(s3c244x_common_dividers,
|
||||
ARRAY_SIZE(s3c244x_common_dividers));
|
||||
samsung_clk_register_gate(s3c244x_common_gates,
|
||||
ARRAY_SIZE(s3c244x_common_gates));
|
||||
samsung_clk_register_mux(s3c244x_common_muxes,
|
||||
ARRAY_SIZE(s3c244x_common_muxes));
|
||||
samsung_clk_register_fixed_factor(s3c244x_common_ffactor,
|
||||
ARRAY_SIZE(s3c244x_common_ffactor));
|
||||
}
|
||||
|
||||
/* Register SoC-specific clocks. */
|
||||
switch (current_soc) {
|
||||
case S3C2410:
|
||||
samsung_clk_register_div(s3c2410_dividers,
|
||||
ARRAY_SIZE(s3c2410_dividers));
|
||||
samsung_clk_register_fixed_factor(s3c2410_ffactor,
|
||||
ARRAY_SIZE(s3c2410_ffactor));
|
||||
samsung_clk_register_alias(s3c2410_aliases,
|
||||
ARRAY_SIZE(s3c2410_common_aliases));
|
||||
break;
|
||||
case S3C2440:
|
||||
samsung_clk_register_mux(s3c2440_muxes,
|
||||
ARRAY_SIZE(s3c2440_muxes));
|
||||
samsung_clk_register_gate(s3c2440_gates,
|
||||
ARRAY_SIZE(s3c2440_gates));
|
||||
break;
|
||||
case S3C2442:
|
||||
samsung_clk_register_mux(s3c2442_muxes,
|
||||
ARRAY_SIZE(s3c2442_muxes));
|
||||
samsung_clk_register_fixed_factor(s3c2442_ffactor,
|
||||
ARRAY_SIZE(s3c2442_ffactor));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register common aliases at the end, as some of the aliased clocks
|
||||
* are SoC specific.
|
||||
*/
|
||||
samsung_clk_register_alias(s3c2410_common_aliases,
|
||||
ARRAY_SIZE(s3c2410_common_aliases));
|
||||
|
||||
if (current_soc == S3C2440 || current_soc == S3C2442) {
|
||||
samsung_clk_register_alias(s3c244x_common_aliases,
|
||||
ARRAY_SIZE(s3c244x_common_aliases));
|
||||
}
|
||||
|
||||
s3c2410_clk_sleep_init();
|
||||
}
|
||||
|
||||
static void __init s3c2410_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2410_common_clk_init(np, 0, S3C2410, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init);
|
||||
|
||||
static void __init s3c2440_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2410_common_clk_init(np, 0, S3C2440, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init);
|
||||
|
||||
static void __init s3c2442_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2410_common_clk_init(np, 0, S3C2442, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init);
|
269
drivers/clk/samsung/clk-s3c2412.c
Normal file
269
drivers/clk/samsung/clk-s3c2412.c
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for S3C2412 and S3C2413.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <dt-bindings/clock/s3c2412.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
#define LOCKTIME 0x00
|
||||
#define MPLLCON 0x04
|
||||
#define UPLLCON 0x08
|
||||
#define CLKCON 0x0c
|
||||
#define CLKDIVN 0x14
|
||||
#define CLKSRC 0x1c
|
||||
|
||||
/* list of PLLs to be registered */
|
||||
enum s3c2412_plls {
|
||||
mpll, upll,
|
||||
};
|
||||
|
||||
static void __iomem *reg_base;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static struct samsung_clk_reg_dump *s3c2412_save;
|
||||
|
||||
/*
|
||||
* list of controller registers to be saved and restored during a
|
||||
* suspend/resume cycle.
|
||||
*/
|
||||
static unsigned long s3c2412_clk_regs[] __initdata = {
|
||||
LOCKTIME,
|
||||
MPLLCON,
|
||||
UPLLCON,
|
||||
CLKCON,
|
||||
CLKDIVN,
|
||||
CLKSRC,
|
||||
};
|
||||
|
||||
static int s3c2412_clk_suspend(void)
|
||||
{
|
||||
samsung_clk_save(reg_base, s3c2412_save,
|
||||
ARRAY_SIZE(s3c2412_clk_regs));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c2412_clk_resume(void)
|
||||
{
|
||||
samsung_clk_restore(reg_base, s3c2412_save,
|
||||
ARRAY_SIZE(s3c2412_clk_regs));
|
||||
}
|
||||
|
||||
static struct syscore_ops s3c2412_clk_syscore_ops = {
|
||||
.suspend = s3c2412_clk_suspend,
|
||||
.resume = s3c2412_clk_resume,
|
||||
};
|
||||
|
||||
static void s3c2412_clk_sleep_init(void)
|
||||
{
|
||||
s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs,
|
||||
ARRAY_SIZE(s3c2412_clk_regs));
|
||||
if (!s3c2412_save) {
|
||||
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
register_syscore_ops(&s3c2412_clk_syscore_ops);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static void s3c2412_clk_sleep_init(void) {}
|
||||
#endif
|
||||
|
||||
static struct clk_div_table divxti_d[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 1, .div = 2 },
|
||||
{ .val = 2, .div = 4 },
|
||||
{ .val = 3, .div = 6 },
|
||||
{ .val = 4, .div = 8 },
|
||||
{ .val = 5, .div = 10 },
|
||||
{ .val = 6, .div = 12 },
|
||||
{ .val = 7, .div = 14 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c2412_dividers[] __initdata = {
|
||||
DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d),
|
||||
DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4),
|
||||
DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4),
|
||||
DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4),
|
||||
DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1),
|
||||
DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1),
|
||||
DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1),
|
||||
DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1),
|
||||
DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2),
|
||||
};
|
||||
|
||||
struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = {
|
||||
FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT),
|
||||
};
|
||||
|
||||
/*
|
||||
* The first two use the OM[4] setting, which is not readable from
|
||||
* software, so assume it is set to xti.
|
||||
*/
|
||||
PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" };
|
||||
PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" };
|
||||
|
||||
PNAME(camclk_p) = { "usysclk", "hclk" };
|
||||
PNAME(usbclk_p) = { "usysclk", "hclk" };
|
||||
PNAME(i2sclk_p) = { "erefclk", "mpll" };
|
||||
PNAME(uartclk_p) = { "erefclk", "mpll" };
|
||||
PNAME(usysclk_p) = { "urefclk", "upll" };
|
||||
PNAME(msysclk_p) = { "mdivclk", "mpll" };
|
||||
PNAME(mdivclk_p) = { "xti", "div_xti" };
|
||||
PNAME(armclk_p) = { "armdiv", "hclk" };
|
||||
|
||||
struct samsung_mux_clock s3c2412_muxes[] __initdata = {
|
||||
MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2),
|
||||
MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2),
|
||||
MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1),
|
||||
MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1),
|
||||
MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1),
|
||||
MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1),
|
||||
MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1),
|
||||
MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1),
|
||||
MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1),
|
||||
MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1),
|
||||
};
|
||||
|
||||
static struct samsung_pll_clock s3c2412_plls[] __initdata = {
|
||||
[mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti",
|
||||
LOCKTIME, MPLLCON, NULL),
|
||||
[upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk",
|
||||
LOCKTIME, UPLLCON, NULL),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2412_gates[] __initdata = {
|
||||
GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0),
|
||||
GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0),
|
||||
GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0),
|
||||
GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0),
|
||||
GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0),
|
||||
GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0),
|
||||
GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0),
|
||||
GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0),
|
||||
GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0),
|
||||
GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0),
|
||||
GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0),
|
||||
GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0),
|
||||
GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0),
|
||||
GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0),
|
||||
GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0),
|
||||
GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0),
|
||||
GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0),
|
||||
GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0),
|
||||
GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0),
|
||||
GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0),
|
||||
GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c2412_aliases[] __initdata = {
|
||||
ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"),
|
||||
ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"),
|
||||
ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"),
|
||||
ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"),
|
||||
ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
|
||||
ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"),
|
||||
ALIAS(PCLK_ADC, NULL, "adc"),
|
||||
ALIAS(PCLK_RTC, NULL, "rtc"),
|
||||
ALIAS(PCLK_PWM, NULL, "timers"),
|
||||
ALIAS(HCLK_LCD, NULL, "lcd"),
|
||||
ALIAS(PCLK_USBD, NULL, "usb-device"),
|
||||
ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"),
|
||||
ALIAS(HCLK_USBH, NULL, "usb-host"),
|
||||
ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
|
||||
ALIAS(ARMCLK, NULL, "armclk"),
|
||||
ALIAS(HCLK, NULL, "hclk"),
|
||||
ALIAS(MPLL, NULL, "mpll"),
|
||||
ALIAS(MSYSCLK, NULL, "fclk"),
|
||||
};
|
||||
|
||||
/*
|
||||
* fixed rate clocks generated outside the soc
|
||||
* Only necessary until the devicetree-move is complete
|
||||
*/
|
||||
#define XTI 1
|
||||
struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = {
|
||||
FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0),
|
||||
FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
|
||||
};
|
||||
|
||||
static void __init s3c2412_common_clk_register_fixed_ext(unsigned long xti_f,
|
||||
unsigned long ext_f)
|
||||
{
|
||||
/* xtal alias is necessary for the current cpufreq driver */
|
||||
struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal");
|
||||
|
||||
s3c2412_common_frate_clks[0].fixed_rate = xti_f;
|
||||
s3c2412_common_frate_clks[1].fixed_rate = ext_f;
|
||||
samsung_clk_register_fixed_rate(s3c2412_common_frate_clks,
|
||||
ARRAY_SIZE(s3c2412_common_frate_clks));
|
||||
|
||||
samsung_clk_register_alias(&xti_alias, 1);
|
||||
}
|
||||
|
||||
void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
unsigned long ext_f, void __iomem *base)
|
||||
{
|
||||
reg_base = base;
|
||||
|
||||
if (np) {
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
}
|
||||
|
||||
samsung_clk_init(np, reg_base, NR_CLKS);
|
||||
|
||||
/* Register external clocks only in non-dt cases */
|
||||
if (!np)
|
||||
s3c2412_common_clk_register_fixed_ext(xti_f, ext_f);
|
||||
|
||||
/* Register PLLs. */
|
||||
samsung_clk_register_pll(s3c2412_plls, ARRAY_SIZE(s3c2412_plls),
|
||||
reg_base);
|
||||
|
||||
/* Register common internal clocks. */
|
||||
samsung_clk_register_mux(s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes));
|
||||
samsung_clk_register_div(s3c2412_dividers,
|
||||
ARRAY_SIZE(s3c2412_dividers));
|
||||
samsung_clk_register_gate(s3c2412_gates, ARRAY_SIZE(s3c2412_gates));
|
||||
samsung_clk_register_fixed_factor(s3c2412_ffactor,
|
||||
ARRAY_SIZE(s3c2412_ffactor));
|
||||
samsung_clk_register_alias(s3c2412_aliases,
|
||||
ARRAY_SIZE(s3c2412_aliases));
|
||||
|
||||
s3c2412_clk_sleep_init();
|
||||
}
|
||||
|
||||
static void __init s3c2412_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2412_common_clk_init(np, 0, 0, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init);
|
462
drivers/clk/samsung/clk-s3c2443.c
Normal file
462
drivers/clk/samsung/clk-s3c2443.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for S3C2443 and following SoCs.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <dt-bindings/clock/s3c2443.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
/* S3C2416 clock controller register offsets */
|
||||
#define LOCKCON0 0x00
|
||||
#define LOCKCON1 0x04
|
||||
#define MPLLCON 0x10
|
||||
#define EPLLCON 0x18
|
||||
#define EPLLCON_K 0x1C
|
||||
#define CLKSRC 0x20
|
||||
#define CLKDIV0 0x24
|
||||
#define CLKDIV1 0x28
|
||||
#define CLKDIV2 0x2C
|
||||
#define HCLKCON 0x30
|
||||
#define PCLKCON 0x34
|
||||
#define SCLKCON 0x38
|
||||
|
||||
/* the soc types */
|
||||
enum supported_socs {
|
||||
S3C2416,
|
||||
S3C2443,
|
||||
S3C2450,
|
||||
};
|
||||
|
||||
/* list of PLLs to be registered */
|
||||
enum s3c2443_plls {
|
||||
mpll, epll,
|
||||
};
|
||||
|
||||
static void __iomem *reg_base;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static struct samsung_clk_reg_dump *s3c2443_save;
|
||||
|
||||
/*
|
||||
* list of controller registers to be saved and restored during a
|
||||
* suspend/resume cycle.
|
||||
*/
|
||||
static unsigned long s3c2443_clk_regs[] __initdata = {
|
||||
LOCKCON0,
|
||||
LOCKCON1,
|
||||
MPLLCON,
|
||||
EPLLCON,
|
||||
EPLLCON_K,
|
||||
CLKSRC,
|
||||
CLKDIV0,
|
||||
CLKDIV1,
|
||||
CLKDIV2,
|
||||
PCLKCON,
|
||||
HCLKCON,
|
||||
SCLKCON,
|
||||
};
|
||||
|
||||
static int s3c2443_clk_suspend(void)
|
||||
{
|
||||
samsung_clk_save(reg_base, s3c2443_save,
|
||||
ARRAY_SIZE(s3c2443_clk_regs));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c2443_clk_resume(void)
|
||||
{
|
||||
samsung_clk_restore(reg_base, s3c2443_save,
|
||||
ARRAY_SIZE(s3c2443_clk_regs));
|
||||
}
|
||||
|
||||
static struct syscore_ops s3c2443_clk_syscore_ops = {
|
||||
.suspend = s3c2443_clk_suspend,
|
||||
.resume = s3c2443_clk_resume,
|
||||
};
|
||||
|
||||
static void s3c2443_clk_sleep_init(void)
|
||||
{
|
||||
s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs,
|
||||
ARRAY_SIZE(s3c2443_clk_regs));
|
||||
if (!s3c2443_save) {
|
||||
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
register_syscore_ops(&s3c2443_clk_syscore_ops);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static void s3c2443_clk_sleep_init(void) {}
|
||||
#endif
|
||||
|
||||
PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" };
|
||||
PNAME(esysclk_p) = { "epllref", "epll" };
|
||||
PNAME(mpllref_p) = { "xti", "mdivclk" };
|
||||
PNAME(msysclk_p) = { "mpllref", "mpll" };
|
||||
PNAME(armclk_p) = { "armdiv" , "hclk" };
|
||||
PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" };
|
||||
|
||||
struct samsung_mux_clock s3c2443_common_muxes[] __initdata = {
|
||||
MUX(0, "epllref", epllref_p, CLKSRC, 7, 2),
|
||||
MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1),
|
||||
MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1),
|
||||
MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"),
|
||||
MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"),
|
||||
MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2),
|
||||
};
|
||||
|
||||
static struct clk_div_table hclk_d[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 1, .div = 2 },
|
||||
{ .val = 3, .div = 4 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct clk_div_table mdivclk_d[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 1, .div = 3 },
|
||||
{ .val = 2, .div = 5 },
|
||||
{ .val = 3, .div = 7 },
|
||||
{ .val = 4, .div = 9 },
|
||||
{ .val = 5, .div = 11 },
|
||||
{ .val = 6, .div = 13 },
|
||||
{ .val = 7, .div = 15 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c2443_common_dividers[] __initdata = {
|
||||
DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d),
|
||||
DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2),
|
||||
DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d),
|
||||
DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1),
|
||||
DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2),
|
||||
DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8),
|
||||
DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4),
|
||||
DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4),
|
||||
DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2),
|
||||
DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2443_common_gates[] __initdata = {
|
||||
GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0),
|
||||
GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0),
|
||||
GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0),
|
||||
GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0),
|
||||
GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0),
|
||||
GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0),
|
||||
GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0),
|
||||
GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0),
|
||||
GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0),
|
||||
GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0),
|
||||
GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0),
|
||||
GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0),
|
||||
GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0),
|
||||
GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0),
|
||||
GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0),
|
||||
GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0),
|
||||
GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0),
|
||||
GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0),
|
||||
GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0),
|
||||
GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0),
|
||||
GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0),
|
||||
GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c2443_common_aliases[] __initdata = {
|
||||
ALIAS(HCLK, NULL, "hclk"),
|
||||
ALIAS(HCLK_SSMC, NULL, "nand"),
|
||||
ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"),
|
||||
ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"),
|
||||
ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"),
|
||||
ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"),
|
||||
ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"),
|
||||
ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"),
|
||||
ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
|
||||
ALIAS(PCLK_PWM, NULL, "timers"),
|
||||
ALIAS(PCLK_RTC, NULL, "rtc"),
|
||||
ALIAS(PCLK_WDT, NULL, "watchdog"),
|
||||
ALIAS(PCLK_ADC, NULL, "adc"),
|
||||
ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"),
|
||||
ALIAS(HCLK_USBD, NULL, "usb-device"),
|
||||
ALIAS(HCLK_USBH, NULL, "usb-host"),
|
||||
ALIAS(SCLK_USBH, NULL, "usb-bus-host"),
|
||||
ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"),
|
||||
ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"),
|
||||
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
|
||||
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
|
||||
ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"),
|
||||
ALIAS(SCLK_I2S0, NULL, "i2s-if"),
|
||||
ALIAS(HCLK_LCD, NULL, "lcd"),
|
||||
ALIAS(SCLK_FIMD, NULL, "sclk_fimd"),
|
||||
};
|
||||
|
||||
/* S3C2416 specific clocks */
|
||||
|
||||
static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = {
|
||||
[mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref",
|
||||
LOCKCON0, MPLLCON, NULL),
|
||||
[epll] = PLL(pll_6553, 0, "epll", "epllref",
|
||||
LOCKCON1, EPLLCON, NULL),
|
||||
};
|
||||
|
||||
PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" };
|
||||
PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" };
|
||||
PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" };
|
||||
|
||||
static struct clk_div_table armdiv_s3c2416_d[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 1, .div = 2 },
|
||||
{ .val = 2, .div = 3 },
|
||||
{ .val = 3, .div = 4 },
|
||||
{ .val = 5, .div = 6 },
|
||||
{ .val = 7, .div = 8 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c2416_dividers[] __initdata = {
|
||||
DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d),
|
||||
DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4),
|
||||
DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2),
|
||||
};
|
||||
|
||||
struct samsung_mux_clock s3c2416_muxes[] __initdata = {
|
||||
MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1),
|
||||
MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1),
|
||||
MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2416_gates[] __initdata = {
|
||||
GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0),
|
||||
GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
|
||||
GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0),
|
||||
GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0),
|
||||
GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0),
|
||||
GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c2416_aliases[] __initdata = {
|
||||
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
|
||||
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
|
||||
ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"),
|
||||
ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
|
||||
ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
|
||||
ALIAS(ARMDIV, NULL, "armdiv"),
|
||||
};
|
||||
|
||||
/* S3C2443 specific clocks */
|
||||
|
||||
static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = {
|
||||
[mpll] = PLL(pll_3000, 0, "mpll", "mpllref",
|
||||
LOCKCON0, MPLLCON, NULL),
|
||||
[epll] = PLL(pll_2126, 0, "epll", "epllref",
|
||||
LOCKCON1, EPLLCON, NULL),
|
||||
};
|
||||
|
||||
static struct clk_div_table armdiv_s3c2443_d[] = {
|
||||
{ .val = 0, .div = 1 },
|
||||
{ .val = 8, .div = 2 },
|
||||
{ .val = 2, .div = 3 },
|
||||
{ .val = 9, .div = 4 },
|
||||
{ .val = 10, .div = 6 },
|
||||
{ .val = 11, .div = 8 },
|
||||
{ .val = 13, .div = 12 },
|
||||
{ .val = 15, .div = 16 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
struct samsung_div_clock s3c2443_dividers[] __initdata = {
|
||||
DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d),
|
||||
DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2443_gates[] __initdata = {
|
||||
GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0),
|
||||
GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0),
|
||||
GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
|
||||
GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0),
|
||||
GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c2443_aliases[] __initdata = {
|
||||
ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"),
|
||||
ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"),
|
||||
ALIAS(SCLK_CAM, NULL, "camif-upll"),
|
||||
ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"),
|
||||
ALIAS(PCLK_SDI, NULL, "sdi"),
|
||||
ALIAS(HCLK_CFC, NULL, "cfc"),
|
||||
ALIAS(ARMDIV, NULL, "armdiv"),
|
||||
};
|
||||
|
||||
/* S3C2450 specific clocks */
|
||||
|
||||
PNAME(s3c2450_cam_p) = { "div_cam", "hclk" };
|
||||
PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" };
|
||||
PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" };
|
||||
|
||||
struct samsung_div_clock s3c2450_dividers[] __initdata = {
|
||||
DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4),
|
||||
DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2),
|
||||
DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4),
|
||||
DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4),
|
||||
};
|
||||
|
||||
struct samsung_mux_clock s3c2450_muxes[] __initdata = {
|
||||
MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1),
|
||||
MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1),
|
||||
MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock s3c2450_gates[] __initdata = {
|
||||
GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0),
|
||||
GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0),
|
||||
GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0),
|
||||
GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0),
|
||||
GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0),
|
||||
GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0),
|
||||
};
|
||||
|
||||
struct samsung_clock_alias s3c2450_aliases[] __initdata = {
|
||||
ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"),
|
||||
ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"),
|
||||
ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"),
|
||||
ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
|
||||
};
|
||||
|
||||
/*
|
||||
* fixed rate clocks generated outside the soc
|
||||
* Only necessary until the devicetree-move is complete
|
||||
*/
|
||||
struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = {
|
||||
FRATE(0, "xti", NULL, CLK_IS_ROOT, 0),
|
||||
FRATE(0, "ext", NULL, CLK_IS_ROOT, 0),
|
||||
FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0),
|
||||
FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0),
|
||||
};
|
||||
|
||||
static void __init s3c2443_common_clk_register_fixed_ext(unsigned long xti_f)
|
||||
{
|
||||
s3c2443_common_frate_clks[0].fixed_rate = xti_f;
|
||||
samsung_clk_register_fixed_rate(s3c2443_common_frate_clks,
|
||||
ARRAY_SIZE(s3c2443_common_frate_clks));
|
||||
}
|
||||
|
||||
void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
|
||||
int current_soc,
|
||||
void __iomem *base)
|
||||
{
|
||||
reg_base = base;
|
||||
|
||||
if (np) {
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
}
|
||||
|
||||
samsung_clk_init(np, reg_base, NR_CLKS);
|
||||
|
||||
/* Register external clocks only in non-dt cases */
|
||||
if (!np)
|
||||
s3c2443_common_clk_register_fixed_ext(xti_f);
|
||||
|
||||
/* Register PLLs. */
|
||||
if (current_soc == S3C2416 || current_soc == S3C2450)
|
||||
samsung_clk_register_pll(s3c2416_pll_clks,
|
||||
ARRAY_SIZE(s3c2416_pll_clks), reg_base);
|
||||
else
|
||||
samsung_clk_register_pll(s3c2443_pll_clks,
|
||||
ARRAY_SIZE(s3c2443_pll_clks), reg_base);
|
||||
|
||||
/* Register common internal clocks. */
|
||||
samsung_clk_register_mux(s3c2443_common_muxes,
|
||||
ARRAY_SIZE(s3c2443_common_muxes));
|
||||
samsung_clk_register_div(s3c2443_common_dividers,
|
||||
ARRAY_SIZE(s3c2443_common_dividers));
|
||||
samsung_clk_register_gate(s3c2443_common_gates,
|
||||
ARRAY_SIZE(s3c2443_common_gates));
|
||||
samsung_clk_register_alias(s3c2443_common_aliases,
|
||||
ARRAY_SIZE(s3c2443_common_aliases));
|
||||
|
||||
/* Register SoC-specific clocks. */
|
||||
switch (current_soc) {
|
||||
case S3C2450:
|
||||
samsung_clk_register_div(s3c2450_dividers,
|
||||
ARRAY_SIZE(s3c2450_dividers));
|
||||
samsung_clk_register_mux(s3c2450_muxes,
|
||||
ARRAY_SIZE(s3c2450_muxes));
|
||||
samsung_clk_register_gate(s3c2450_gates,
|
||||
ARRAY_SIZE(s3c2450_gates));
|
||||
samsung_clk_register_alias(s3c2450_aliases,
|
||||
ARRAY_SIZE(s3c2450_aliases));
|
||||
/* fall through, as s3c2450 extends the s3c2416 clocks */
|
||||
case S3C2416:
|
||||
samsung_clk_register_div(s3c2416_dividers,
|
||||
ARRAY_SIZE(s3c2416_dividers));
|
||||
samsung_clk_register_mux(s3c2416_muxes,
|
||||
ARRAY_SIZE(s3c2416_muxes));
|
||||
samsung_clk_register_gate(s3c2416_gates,
|
||||
ARRAY_SIZE(s3c2416_gates));
|
||||
samsung_clk_register_alias(s3c2416_aliases,
|
||||
ARRAY_SIZE(s3c2416_aliases));
|
||||
break;
|
||||
case S3C2443:
|
||||
samsung_clk_register_div(s3c2443_dividers,
|
||||
ARRAY_SIZE(s3c2443_dividers));
|
||||
samsung_clk_register_gate(s3c2443_gates,
|
||||
ARRAY_SIZE(s3c2443_gates));
|
||||
samsung_clk_register_alias(s3c2443_aliases,
|
||||
ARRAY_SIZE(s3c2443_aliases));
|
||||
break;
|
||||
}
|
||||
|
||||
s3c2443_clk_sleep_init();
|
||||
}
|
||||
|
||||
static void __init s3c2416_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2443_common_clk_init(np, 0, S3C2416, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init);
|
||||
|
||||
static void __init s3c2443_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2443_common_clk_init(np, 0, S3C2443, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init);
|
||||
|
||||
static void __init s3c2450_clk_init(struct device_node *np)
|
||||
{
|
||||
s3c2443_common_clk_init(np, 0, S3C2450, 0);
|
||||
}
|
||||
CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init);
|
@ -141,6 +141,7 @@ static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
|
||||
|
||||
static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg)
|
||||
{
|
||||
cfg->mpll = _clk_mpll;
|
||||
(cfg->info->set_fvco)(cfg);
|
||||
}
|
||||
|
||||
|
62
include/dt-bindings/clock/s3c2410.h
Normal file
62
include/dt-bindings/clock/s3c2410.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Device Tree binding constants clock controllers of Samsung S3C2410 and later.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2410_CLOCK_H
|
||||
#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2410_CLOCK_H
|
||||
|
||||
/*
|
||||
* Let each exported clock get a unique index, which is used on DT-enabled
|
||||
* platforms to lookup the clock from a clock specifier. These indices are
|
||||
* therefore considered an ABI and so must not be changed. This implies
|
||||
* that new clocks should be added either in free spaces between clock groups
|
||||
* or at the end.
|
||||
*/
|
||||
|
||||
/* Core clocks. */
|
||||
|
||||
/* id 1 is reserved */
|
||||
#define MPLL 2
|
||||
#define UPLL 3
|
||||
#define FCLK 4
|
||||
#define HCLK 5
|
||||
#define PCLK 6
|
||||
#define UCLK 7
|
||||
#define ARMCLK 8
|
||||
|
||||
/* pclk-gates */
|
||||
#define PCLK_UART0 16
|
||||
#define PCLK_UART1 17
|
||||
#define PCLK_UART2 18
|
||||
#define PCLK_I2C 19
|
||||
#define PCLK_SDI 20
|
||||
#define PCLK_SPI 21
|
||||
#define PCLK_ADC 22
|
||||
#define PCLK_AC97 23
|
||||
#define PCLK_I2S 24
|
||||
#define PCLK_PWM 25
|
||||
#define PCLK_RTC 26
|
||||
#define PCLK_GPIO 27
|
||||
|
||||
|
||||
/* hclk-gates */
|
||||
#define HCLK_LCD 32
|
||||
#define HCLK_USBH 33
|
||||
#define HCLK_USBD 34
|
||||
#define HCLK_NAND 35
|
||||
#define HCLK_CAM 36
|
||||
|
||||
|
||||
#define CAMIF 40
|
||||
|
||||
|
||||
/* Total number of clocks. */
|
||||
#define NR_CLKS (CAMIF + 1)
|
||||
|
||||
#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */
|
73
include/dt-bindings/clock/s3c2412.h
Normal file
73
include/dt-bindings/clock/s3c2412.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Device Tree binding constants clock controllers of Samsung S3C2412.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H
|
||||
#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H
|
||||
|
||||
/*
|
||||
* Let each exported clock get a unique index, which is used on DT-enabled
|
||||
* platforms to lookup the clock from a clock specifier. These indices are
|
||||
* therefore considered an ABI and so must not be changed. This implies
|
||||
* that new clocks should be added either in free spaces between clock groups
|
||||
* or at the end.
|
||||
*/
|
||||
|
||||
/* Core clocks. */
|
||||
|
||||
/* id 1 is reserved */
|
||||
#define MPLL 2
|
||||
#define UPLL 3
|
||||
#define MDIVCLK 4
|
||||
#define MSYSCLK 5
|
||||
#define USYSCLK 6
|
||||
#define HCLK 7
|
||||
#define PCLK 8
|
||||
#define ARMDIV 9
|
||||
#define ARMCLK 10
|
||||
|
||||
|
||||
/* Special clocks */
|
||||
#define SCLK_CAM 16
|
||||
#define SCLK_UART 17
|
||||
#define SCLK_I2S 18
|
||||
#define SCLK_USBD 19
|
||||
#define SCLK_USBH 20
|
||||
|
||||
/* pclk-gates */
|
||||
#define PCLK_WDT 32
|
||||
#define PCLK_SPI 33
|
||||
#define PCLK_I2S 34
|
||||
#define PCLK_I2C 35
|
||||
#define PCLK_ADC 36
|
||||
#define PCLK_RTC 37
|
||||
#define PCLK_GPIO 38
|
||||
#define PCLK_UART2 39
|
||||
#define PCLK_UART1 40
|
||||
#define PCLK_UART0 41
|
||||
#define PCLK_SDI 42
|
||||
#define PCLK_PWM 43
|
||||
#define PCLK_USBD 44
|
||||
|
||||
/* hclk-gates */
|
||||
#define HCLK_HALF 48
|
||||
#define HCLK_X2 49
|
||||
#define HCLK_SDRAM 50
|
||||
#define HCLK_USBH 51
|
||||
#define HCLK_LCD 52
|
||||
#define HCLK_NAND 53
|
||||
#define HCLK_DMA3 54
|
||||
#define HCLK_DMA2 55
|
||||
#define HCLK_DMA1 56
|
||||
#define HCLK_DMA0 57
|
||||
|
||||
/* Total number of clocks. */
|
||||
#define NR_CLKS (HCLK_DMA0 + 1)
|
||||
|
||||
#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H */
|
92
include/dt-bindings/clock/s3c2443.h
Normal file
92
include/dt-bindings/clock/s3c2443.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Device Tree binding constants clock controllers of Samsung S3C2443 and later.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H
|
||||
#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H
|
||||
|
||||
/*
|
||||
* Let each exported clock get a unique index, which is used on DT-enabled
|
||||
* platforms to lookup the clock from a clock specifier. These indices are
|
||||
* therefore considered an ABI and so must not be changed. This implies
|
||||
* that new clocks should be added either in free spaces between clock groups
|
||||
* or at the end.
|
||||
*/
|
||||
|
||||
/* Core clocks. */
|
||||
#define MSYSCLK 1
|
||||
#define ESYSCLK 2
|
||||
#define ARMDIV 3
|
||||
#define ARMCLK 4
|
||||
#define HCLK 5
|
||||
#define PCLK 6
|
||||
|
||||
/* Special clocks */
|
||||
#define SCLK_HSSPI0 16
|
||||
#define SCLK_FIMD 17
|
||||
#define SCLK_I2S0 18
|
||||
#define SCLK_I2S1 19
|
||||
#define SCLK_HSMMC1 20
|
||||
#define SCLK_HSMMC_EXT 21
|
||||
#define SCLK_CAM 22
|
||||
#define SCLK_UART 23
|
||||
#define SCLK_USBH 24
|
||||
|
||||
/* Muxes */
|
||||
#define MUX_HSSPI0 32
|
||||
#define MUX_HSSPI1 33
|
||||
#define MUX_HSMMC0 34
|
||||
#define MUX_HSMMC1 35
|
||||
|
||||
/* hclk-gates */
|
||||
#define HCLK_DMA0 48
|
||||
#define HCLK_DMA1 49
|
||||
#define HCLK_DMA2 50
|
||||
#define HCLK_DMA3 51
|
||||
#define HCLK_DMA4 52
|
||||
#define HCLK_DMA5 53
|
||||
#define HCLK_DMA6 54
|
||||
#define HCLK_DMA7 55
|
||||
#define HCLK_CAM 56
|
||||
#define HCLK_LCD 57
|
||||
#define HCLK_USBH 58
|
||||
#define HCLK_USBD 59
|
||||
#define HCLK_IROM 60
|
||||
#define HCLK_HSMMC0 61
|
||||
#define HCLK_HSMMC1 62
|
||||
#define HCLK_CFC 63
|
||||
#define HCLK_SSMC 64
|
||||
#define HCLK_DRAM 65
|
||||
#define HCLK_2D 66
|
||||
|
||||
/* pclk-gates */
|
||||
#define PCLK_UART0 72
|
||||
#define PCLK_UART1 73
|
||||
#define PCLK_UART2 74
|
||||
#define PCLK_UART3 75
|
||||
#define PCLK_I2C0 76
|
||||
#define PCLK_SDI 77
|
||||
#define PCLK_SPI0 78
|
||||
#define PCLK_ADC 79
|
||||
#define PCLK_AC97 80
|
||||
#define PCLK_I2S0 81
|
||||
#define PCLK_PWM 82
|
||||
#define PCLK_WDT 83
|
||||
#define PCLK_RTC 84
|
||||
#define PCLK_GPIO 85
|
||||
#define PCLK_SPI1 86
|
||||
#define PCLK_CHIPID 87
|
||||
#define PCLK_I2C1 88
|
||||
#define PCLK_I2S1 89
|
||||
#define PCLK_PCM 90
|
||||
|
||||
/* Total number of clocks. */
|
||||
#define NR_CLKS (PCLK_PCM + 1)
|
||||
|
||||
#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */
|
Loading…
Reference in New Issue
Block a user