Commit b5783dca authored by Kukjin Kim's avatar Kukjin Kim

Merge branch 'v3.16-next/clk-s3c24xx-3' into v3.16-next/cleanup-samsung

parents 702b691e 34c453ce
* 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";
};
* 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";
};
* 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 @@ memory {
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 @@ interrupt-controller@4a000000 {
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 @@ sdhci@4AC00000 {
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 @@ sdhci@4A800000 {
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
#
......
/*
* 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,
};
/*
* 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;
}
This diff is collapsed.
/* 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));
}
/* 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);
/* 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));
}
/* 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);
This diff is collapsed.
......@@ -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) \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment