The common clk framework changes for 3.12 are dominated by clock driver

patches, both new drivers and fixes to existing. A high percentage of
 these are for Samsung platforms like Exynos. Core framework fixes and
 some new features like automagical clock re-parenting round out the
 patches.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJSLkImAAoJEDqPOy9afJhJOjsP/Ri26AW7XB9pPWJRSU9REBZA
 31wxcFo2T+PNir9duwDwjFBFycC3MisaKFlg7D134M+7txbYqm1TRvfu9OEDxpSP
 4b/Yl6TarN4dhCN2R+BREO8PnxCBVpspDcsdh6Esuwuet2xUom3UtN8yvSjhPP/u
 qGNmXQYXyQy4fom5r+GsDVW+HIhLkaX9b0fYc9EN/bqfgv94PMZAxAxsK9CroAGZ
 0m0g9ZXw9iSvVfz+iQEqPINtvpTLHk0FGyimoSR7kvW4o4o47tVtLEWp7VjG6mr5
 zvBsycaQq6NgxPu96iUWWhsO9Uj2I7/7JgidXF7r+wvEFs1mcgZtkkirSA/n4zUN
 C8a87rvQrZRLr+xXhVuqiVHCgCY8vXoHqkWg6SrZ62ORL8C7uYRpog5SEe2ZzLJX
 l5uGAsDM6el+Uc/YviCPoZbeFr3h3CQvvFo8+i2eN0v/Phf30rq4lotBvpQj894G
 ngEIMj+D8wshdYSF2dNJ0rLnkLHTgCbiA28L6Cl5TRzRMj3Uaj9aT3cmoLUnimZu
 7F7nWU4Iu/vzQKCTQ+eTvwxXJqIlE0JeVbJilqH1f2a68JdXP1LOId+2w/CP8gqQ
 i2odj6JHMgBzM9rNs+y0Ir9X/bXIVi6F341c19Nl15srEiLLl8xQIpcPDaI/Kvzs
 pefYgF2yS5AZAW3ac90r
 =5GfA
 -----END PGP SIGNATURE-----

Merge tag 'clk-for-linus-3.12' of git://git.linaro.org/people/mturquette/linux

Pull clock framework changes from Michael Turquette:
 "The common clk framework changes for 3.12 are dominated by clock
  driver patches, both new drivers and fixes to existing.  A high
  percentage of these are for Samsung platforms like Exynos.  Core
  framework fixes and some new features like automagical clock
  re-parenting round out the patches"

* tag 'clk-for-linus-3.12' of git://git.linaro.org/people/mturquette/linux: (102 commits)
  clk: only call get_parent if there is one
  clk: samsung: exynos5250: Simplify registration of PLL rate tables
  clk: samsung: exynos4: Register PLL rate tables for Exynos4x12
  clk: samsung: exynos4: Register PLL rate tables for Exynos4210
  clk: samsung: exynos4: Reorder registration of mout_vpllsrc
  clk: samsung: pll: Add support for rate configuration of PLL46xx
  clk: samsung: pll: Use new registration method for PLL46xx
  clk: samsung: pll: Add support for rate configuration of PLL45xx
  clk: samsung: pll: Use new registration method for PLL45xx
  clk: samsung: exynos4: Rename exynos4_plls to exynos4x12_plls
  clk: samsung: exynos4: Remove checks for DT node
  clk: samsung: exynos4: Remove unused static clkdev aliases
  clk: samsung: Modify _get_rate() helper to use __clk_lookup()
  clk: samsung: exynos4: Use separate aliases for cpufreq related clocks
  clocksource: samsung_pwm_timer: Get clock from device tree
  ARM: dts: exynos4: Specify PWM clocks in PWM node
  pwm: samsung: Update DT bindings documentation to cover clocks
  clk: Move symbol export to proper location
  clk: fix new_parent dereference before null check
  clk: wm831x: Initialise wm831x pointer on init
  ...
This commit is contained in:
Linus Torvalds 2013-09-09 15:49:04 -07:00
commit bef4a0ab98
64 changed files with 3611 additions and 1117 deletions

View File

@ -70,6 +70,10 @@ the operations defined in clk.h:
unsigned long parent_rate);
long (*round_rate)(struct clk_hw *hw, unsigned long,
unsigned long *);
long (*determine_rate)(struct clk_hw *hw,
unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw, unsigned long);
@ -179,26 +183,28 @@ mandatory, a cell marked as "n" implies that either including that
callback is invalid or otherwise unnecessary. Empty cells are either
optional or must be evaluated on a case-by-case basis.
clock hardware characteristics
-----------------------------------------------------------
| gate | change rate | single parent | multiplexer | root |
|------|-------------|---------------|-------------|------|
.prepare | | | | | |
.unprepare | | | | | |
| | | | | |
.enable | y | | | | |
.disable | y | | | | |
.is_enabled | y | | | | |
| | | | | |
.recalc_rate | | y | | | |
.round_rate | | y | | | |
.set_rate | | y | | | |
| | | | | |
.set_parent | | | n | y | n |
.get_parent | | | n | y | n |
| | | | | |
.init | | | | | |
-----------------------------------------------------------
clock hardware characteristics
-----------------------------------------------------------
| gate | change rate | single parent | multiplexer | root |
|------|-------------|---------------|-------------|------|
.prepare | | | | | |
.unprepare | | | | | |
| | | | | |
.enable | y | | | | |
.disable | y | | | | |
.is_enabled | y | | | | |
| | | | | |
.recalc_rate | | y | | | |
.round_rate | | y [1] | | | |
.determine_rate | | y [1] | | | |
.set_rate | | y | | | |
| | | | | |
.set_parent | | | n | y | n |
.get_parent | | | n | y | n |
| | | | | |
.init | | | | | |
-----------------------------------------------------------
[1] either one of round_rate or determine_rate is required.
Finally, register your clock at run-time with a hardware-specific
registration function. This function simply populates struct clk_foo's

View File

@ -236,6 +236,7 @@ Exynos4 SoC and this is specified where applicable.
spi0_isp_sclk 380 Exynos4x12
spi1_isp_sclk 381 Exynos4x12
uart_isp_sclk 382 Exynos4x12
tmu_apbif 383
[Mux Clocks]

View File

@ -59,6 +59,9 @@ clock which they consume.
sclk_spi0 154
sclk_spi1 155
sclk_spi2 156
div_i2s1 157
div_i2s2 158
sclk_hdmiphy 159
[Peripheral Clock Gates]
@ -154,7 +157,16 @@ clock which they consume.
dsim0 341
dp 342
mixer 343
hdmi 345
hdmi 344
g2d 345
[Clock Muxes]
Clock ID
----------------------------
mout_hdmi 1024
Example 1: An example of a clock controller node is listed below.

View File

@ -59,6 +59,7 @@ clock which they consume.
sclk_pwm 155
sclk_gscl_wa 156
sclk_gscl_wb 157
sclk_hdmiphy 158
[Peripheral Clock Gates]
@ -179,6 +180,17 @@ clock which they consume.
fimc_lite3 495
aclk_g3d 500
g3d 501
smmu_mixer 502
Mux ID
----------------------------
mout_hdmi 640
Divider ID
----------------------------
dout_pixel 768
Example 1: An example of a clock controller node is listed below.

View File

@ -0,0 +1,77 @@
* Samsung S3C64xx Clock Controller
The S3C64xx clock controller generates and supplies clock to various controllers
within the SoC. The clock binding described here is applicable to all SoCs in
the S3C64xx family.
Required Properties:
- compatible: should be one of the following.
- "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC.
- "samsung,s3c6410-clock" - controller compatible with S3C6410 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 S3C64xx SoC and this is specified where applicable.
All available clocks are defined as preprocessor macros in
dt-bindings/clock/samsung,s3c64xx-clock.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:
- "fin_pll" - PLL input clock (xtal/extclk) - required,
- "xusbxti" - USB xtal - required,
- "iiscdclk0" - I2S0 codec clock - optional,
- "iiscdclk1" - I2S1 codec clock - optional,
- "iiscdclk2" - I2S2 codec clock - optional,
- "pcmcdclk0" - PCM0 codec clock - optional,
- "pcmcdclk1" - PCM1 codec clock - optional, only S3C6410.
Example: Clock controller node:
clock: clock-controller@7e00f000 {
compatible = "samsung,s3c6410-clock";
reg = <0x7e00f000 0x1000>;
#clock-cells = <1>;
};
Example: Required external clocks:
fin_pll: clock-fin-pll {
compatible = "fixed-clock";
clock-output-names = "fin_pll";
clock-frequency = <12000000>;
#clock-cells = <0>;
};
xusbxti: clock-xusbxti {
compatible = "fixed-clock";
clock-output-names = "xusbxti";
clock-frequency = <48000000>;
#clock-cells = <0>;
};
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):
uart0: serial@7f005000 {
compatible = "samsung,s3c6400-uart";
reg = <0x7f005000 0x100>;
interrupt-parent = <&vic1>;
interrupts = <5>;
clock-names = "uart", "clk_uart_baud2",
"clk_uart_baud3";
clocks = <&clock PCLK_UART0>, <&clocks PCLK_UART0>,
<&clock SCLK_UART>;
status = "disabled";
};

View File

@ -8,19 +8,31 @@ Required properties:
- compatible : shall be one of the following:
"allwinner,sun4i-osc-clk" - for a gatable oscillator
"allwinner,sun4i-pll1-clk" - for the main PLL clock
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
"allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-axi-clk" - for the AXI clock
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
"allwinner,sun4i-ahb-clk" - for the AHB clock
"allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10
"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
"allwinner,sun4i-apb0-clk" - for the APB0 clock
"allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
"allwinner,sun4i-apb1-clk" - for the APB1 clock
"allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
"allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10
"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
Required properties for all clocks:
- reg : shall be the control register address for the clock.

View File

@ -0,0 +1,75 @@
Gate clock outputs
------------------
* AXI gates ("allwinner,sun4i-axi-gates-clk")
DRAM 0
* AHB gates ("allwinner,sun5i-a10s-ahb-gates-clk")
USB0 0
EHCI0 1
OHCI0 2
SS 5
DMA 6
BIST 7
MMC0 8
MMC1 9
MMC2 10
NAND 13
SDRAM 14
EMAC 17
TS 18
SPI0 20
SPI1 21
SPI2 22
GPS 26
HSTIMER 28
VE 32
TVE 34
LCD 36
CSI 40
HDMI 43
DE_BE 44
DE_FE 46
IEP 51
MALI400 52
* APB0 gates ("allwinner,sun5i-a10s-apb0-gates-clk")
CODEC 0
IIS 3
PIO 5
IR 6
KEYPAD 10
* APB1 gates ("allwinner,sun5i-a10s-apb1-gates-clk")
I2C0 0
I2C1 1
I2C2 2
UART0 16
UART1 17
UART2 18
UART3 19
Notation:
[*]: The datasheet didn't mention these, but they are present on AW code
[**]: The datasheet had this marked as "NC" but they are used on AW code

View File

@ -0,0 +1,83 @@
Gate clock outputs
------------------
* AHB1 gates ("allwinner,sun6i-a31-ahb1-gates-clk")
MIPI DSI 1
SS 5
DMA 6
MMC0 8
MMC1 9
MMC2 10
MMC3 11
NAND1 12
NAND0 13
SDRAM 14
GMAC 17
TS 18
HSTIMER 19
SPI0 20
SPI1 21
SPI2 22
SPI3 23
USB_OTG 24
EHCI0 26
EHCI1 27
OHCI0 29
OHCI1 30
OHCI2 31
VE 32
LCD0 36
LCD1 37
CSI 40
HDMI 43
DE_BE0 44
DE_BE1 45
DE_FE1 46
DE_FE1 47
MP 50
GPU 52
DEU0 55
DEU1 56
DRC0 57
DRC1 58
* APB1 gates ("allwinner,sun6i-a31-apb1-gates-clk")
CODEC 0
DIGITAL MIC 4
PIO 5
DAUDIO0 12
DAUDIO1 13
* APB2 gates ("allwinner,sun6i-a31-apb2-gates-clk")
I2C0 0
I2C1 1
I2C2 2
I2C3 3
UART0 16
UART1 17
UART2 18
UART3 19
UART4 20
UART5 21
Notation:
[*]: The datasheet didn't mention these, but they are present on AW code
[**]: The datasheet had this marked as "NC" but they are used on AW code

View File

@ -0,0 +1,98 @@
Gate clock outputs
------------------
* AXI gates ("allwinner,sun4i-axi-gates-clk")
DRAM 0
* AHB gates ("allwinner,sun7i-a20-ahb-gates-clk")
USB0 0
EHCI0 1
OHCI0 2
EHCI1 3
OHCI1 4
SS 5
DMA 6
BIST 7
MMC0 8
MMC1 9
MMC2 10
MMC3 11
MS 12
NAND 13
SDRAM 14
ACE 16
EMAC 17
TS 18
SPI0 20
SPI1 21
SPI2 22
SPI3 23
SATA 25
HSTIMER 28
VE 32
TVD 33
TVE0 34
TVE1 35
LCD0 36
LCD1 37
CSI0 40
CSI1 41
HDMI1 42
HDMI0 43
DE_BE0 44
DE_BE1 45
DE_FE1 46
DE_FE1 47
GMAC 49
MP 50
MALI400 52
* APB0 gates ("allwinner,sun7i-a20-apb0-gates-clk")
CODEC 0
SPDIF 1
AC97 2
IIS0 3
IIS1 4
PIO 5
IR0 6
IR1 7
IIS2 8
KEYPAD 10
* APB1 gates ("allwinner,sun7i-a20-apb1-gates-clk")
I2C0 0
I2C1 1
I2C2 2
I2C3 3
CAN 4
SCR 5
PS20 6
PS21 7
I2C4 15
UART0 16
UART1 17
UART2 18
UART3 19
UART4 20
UART5 21
UART6 22
UART7 23
Notation:
[*]: The datasheet didn't mention these, but they are present on AW code
[**]: The datasheet had this marked as "NC" but they are used on AW code

View File

@ -11,8 +11,11 @@ Required properties:
- interrupts : G2D interrupt number to the CPU.
- clocks : from common clock binding: handle to G2D clocks.
- clock-names : from common clock binding: must contain "sclk_fimg2d" and
"fimg2d", corresponding to entries in the clocks property.
- clock-names : names of clocks listed in clocks property, in the same
order, depending on SoC type:
- for S5PV210 and Exynos4 based SoCs: "fimg2d" and
"sclk_fimg2d"
- for Exynos5250 SoC: "fimg2d".
Example:
g2d@12800000 {

View File

@ -19,6 +19,16 @@ Required properties:
- reg: base address and size of register area
- interrupts: list of timer interrupts (one interrupt per timer, starting at
timer 0)
- clock-names: should contain all following required clock names:
- "timers" - PWM base clock used to generate PWM signals,
and any subset of following optional clock names:
- "pwm-tclk0" - first external PWM clock source,
- "pwm-tclk1" - second external PWM clock source.
Note that not all IP variants allow using all external clock sources.
Refer to SoC documentation to learn which clock source configurations
are available.
- clocks: should contain clock specifiers of all clocks, which input names
have been specified in clock-names property, in same order.
- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
the cells format. The only third cell flag supported by this binding is
PWM_POLARITY_INVERTED.
@ -34,6 +44,8 @@ Example:
reg = <0x7f006000 0x1000>;
interrupt-parent = <&vic0>;
interrupts = <23>, <24>, <25>, <27>, <28>;
clocks = <&clock 67>;
clock-names = "timers";
samsung,pwm-outputs = <0>, <1>;
#pwm-cells = <3>;
}

View File

@ -448,6 +448,8 @@
compatible = "samsung,exynos4210-pwm";
reg = <0x139D0000 0x1000>;
interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>;
clocks = <&clock 336>;
clock-names = "timers";
#pwm-cells = <2>;
status = "disabled";
};

View File

@ -89,7 +89,8 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent,
static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parents, int num_parents)
{
return clk_register_mux(NULL, name, parents, num_parents, 0, reg, shift,
return clk_register_mux(NULL, name, parents, num_parents,
CLK_SET_RATE_NO_REPARENT, reg, shift,
width, 0, &imx_ccm_lock);
}
@ -98,7 +99,7 @@ static inline struct clk *imx_clk_mux_flags(const char *name,
int num_parents, unsigned long flags)
{
return clk_register_mux(NULL, name, parents, num_parents,
flags, reg, shift, width, 0,
flags | CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0,
&imx_ccm_lock);
}

View File

@ -27,7 +27,7 @@ config COMMON_CLK_DEBUG
bool "DebugFS representation of clock tree"
select DEBUG_FS
---help---
Creates a directory hierchy in debugfs for visualizing the clk
Creates a directory hierarchy in debugfs for visualizing the clk
tree structure. Each directory contains read-only members
that export information specific to that clk node: clk_rate,
clk_flags, clk_prepare_count, clk_enable_count &
@ -64,6 +64,12 @@ config COMMON_CLK_SI5351
This driver supports Silicon Labs 5351A/B/C programmable clock
generators.
config COMMON_CLK_S2MPS11
tristate "Clock driver for S2MPS11 MFD"
depends on MFD_SEC_CORE
---help---
This driver supports S2MPS11 crystal oscillator clock.
config CLK_TWL6040
tristate "External McPDM functional clock from twl6040"
depends on TWL6040_CORE

View File

@ -40,5 +40,6 @@ obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o

View File

@ -23,7 +23,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
static const __initconst struct of_device_id clk_match[] = {
static const struct of_device_id clk_match[] __initconst = {
{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
{ }
};

View File

@ -104,7 +104,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
struct clk_divider *divider = to_clk_divider(hw);
unsigned int div, val;
val = readl(divider->reg) >> divider->shift;
val = clk_readl(divider->reg) >> divider->shift;
val &= div_mask(divider);
div = _get_div(divider, val);
@ -230,11 +230,11 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
val = div_mask(divider) << (divider->shift + 16);
} else {
val = readl(divider->reg);
val = clk_readl(divider->reg);
val &= ~(div_mask(divider) << divider->shift);
}
val |= value << divider->shift;
writel(val, divider->reg);
clk_writel(val, divider->reg);
if (divider->lock)
spin_unlock_irqrestore(divider->lock, flags);
@ -317,6 +317,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
return _register_divider(dev, name, parent_name, flags, reg, shift,
width, clk_divider_flags, NULL, lock);
}
EXPORT_SYMBOL_GPL(clk_register_divider);
/**
* clk_register_divider_table - register a table based divider clock with
@ -341,3 +342,4 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
return _register_divider(dev, name, parent_name, flags, reg, shift,
width, clk_divider_flags, table, lock);
}
EXPORT_SYMBOL_GPL(clk_register_divider_table);

View File

@ -97,6 +97,8 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
return clk;
}
EXPORT_SYMBOL_GPL(clk_register_fixed_factor);
#ifdef CONFIG_OF
/**
* of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock

View File

@ -80,6 +80,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
return clk;
}
EXPORT_SYMBOL_GPL(clk_register_fixed_rate);
#ifdef CONFIG_OF
/**

View File

@ -58,7 +58,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
if (set)
reg |= BIT(gate->bit_idx);
} else {
reg = readl(gate->reg);
reg = clk_readl(gate->reg);
if (set)
reg |= BIT(gate->bit_idx);
@ -66,7 +66,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
reg &= ~BIT(gate->bit_idx);
}
writel(reg, gate->reg);
clk_writel(reg, gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
@ -89,7 +89,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw)
u32 reg;
struct clk_gate *gate = to_clk_gate(hw);
reg = readl(gate->reg);
reg = clk_readl(gate->reg);
/* if a set bit disables this clk, flip it before masking */
if (gate->flags & CLK_GATE_SET_TO_DISABLE)
@ -161,3 +161,4 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
return clk;
}
EXPORT_SYMBOL_GPL(clk_register_gate);

View File

@ -42,7 +42,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
* OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
* val = 0x4 really means "bit 2, index starts at bit 0"
*/
val = readl(mux->reg) >> mux->shift;
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
if (mux->table) {
@ -89,11 +89,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16);
} else {
val = readl(mux->reg);
val = clk_readl(mux->reg);
val &= ~(mux->mask << mux->shift);
}
val |= index << mux->shift;
writel(val, mux->reg);
clk_writel(val, mux->reg);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
@ -104,9 +104,15 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
const struct clk_ops clk_mux_ops = {
.get_parent = clk_mux_get_parent,
.set_parent = clk_mux_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_mux_ops);
const struct clk_ops clk_mux_ro_ops = {
.get_parent = clk_mux_get_parent,
};
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
@ -133,7 +139,10 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
}
init.name = name;
init.ops = &clk_mux_ops;
if (clk_mux_flags & CLK_MUX_READ_ONLY)
init.ops = &clk_mux_ro_ops;
else
init.ops = &clk_mux_ops;
init.flags = flags | CLK_IS_BASIC;
init.parent_names = parent_names;
init.num_parents = num_parents;
@ -154,6 +163,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
return clk;
}
EXPORT_SYMBOL_GPL(clk_register_mux_table);
struct clk *clk_register_mux(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
@ -166,3 +176,4 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
flags, reg, shift, mask, clk_mux_flags,
NULL, lock);
}
EXPORT_SYMBOL_GPL(clk_register_mux);

View File

@ -479,12 +479,12 @@ static void __init of_nomadik_src_clk_setup(struct device_node *np)
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
static const __initconst struct of_device_id nomadik_src_match[] = {
static const struct of_device_id nomadik_src_match[] __initconst = {
{ .compatible = "stericsson,nomadik-src" },
{ /* sentinel */ }
};
static const __initconst struct of_device_id nomadik_src_clk_match[] = {
static const struct of_device_id nomadik_src_clk_match[] __initconst = {
{
.compatible = "fixed-clock",
.data = of_fixed_clk_setup,

View File

@ -1034,7 +1034,7 @@ enum prima2_clk_index {
usb0, usb1, maxclk,
};
static __initdata struct clk_hw* prima2_clk_hw_array[maxclk] = {
static struct clk_hw *prima2_clk_hw_array[maxclk] __initdata = {
NULL, /* dummy */
NULL,
&clk_pll1.hw,

273
drivers/clk/clk-s2mps11.c Normal file
View File

@ -0,0 +1,273 @@
/*
* clk-s2mps11.c - Clock driver for S2MPS11.
*
* Copyright (C) 2013 Samsung Electornics
*
* 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/module.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clkdev.h>
#include <linux/regmap.h>
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/core.h>
#define s2mps11_name(a) (a->hw.init->name)
static struct clk **clk_table;
static struct clk_onecell_data clk_data;
enum {
S2MPS11_CLK_AP = 0,
S2MPS11_CLK_CP,
S2MPS11_CLK_BT,
S2MPS11_CLKS_NUM,
};
struct s2mps11_clk {
struct sec_pmic_dev *iodev;
struct clk_hw hw;
struct clk *clk;
struct clk_lookup *lookup;
u32 mask;
bool enabled;
};
static struct s2mps11_clk *to_s2mps11_clk(struct clk_hw *hw)
{
return container_of(hw, struct s2mps11_clk, hw);
}
static int s2mps11_clk_prepare(struct clk_hw *hw)
{
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
int ret;
ret = regmap_update_bits(s2mps11->iodev->regmap,
S2MPS11_REG_RTC_CTRL,
s2mps11->mask, s2mps11->mask);
if (!ret)
s2mps11->enabled = true;
return ret;
}
static void s2mps11_clk_unprepare(struct clk_hw *hw)
{
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
int ret;
ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
s2mps11->mask, ~s2mps11->mask);
if (!ret)
s2mps11->enabled = false;
}
static int s2mps11_clk_is_enabled(struct clk_hw *hw)
{
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
return s2mps11->enabled;
}
static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
if (s2mps11->enabled)
return 32768;
else
return 0;
}
static struct clk_ops s2mps11_clk_ops = {
.prepare = s2mps11_clk_prepare,
.unprepare = s2mps11_clk_unprepare,
.is_enabled = s2mps11_clk_is_enabled,
.recalc_rate = s2mps11_clk_recalc_rate,
};
static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
[S2MPS11_CLK_AP] = {
.name = "s2mps11_ap",
.ops = &s2mps11_clk_ops,
.flags = CLK_IS_ROOT,
},
[S2MPS11_CLK_CP] = {
.name = "s2mps11_cp",
.ops = &s2mps11_clk_ops,
.flags = CLK_IS_ROOT,
},
[S2MPS11_CLK_BT] = {
.name = "s2mps11_bt",
.ops = &s2mps11_clk_ops,
.flags = CLK_IS_ROOT,
},
};
static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct device_node *clk_np;
int i;
if (!iodev->dev->of_node)
return NULL;
clk_np = of_find_node_by_name(iodev->dev->of_node, "clocks");
if (!clk_np) {
dev_err(&pdev->dev, "could not find clock sub-node\n");
return ERR_PTR(-EINVAL);
}
clk_table = devm_kzalloc(&pdev->dev, sizeof(struct clk *) *
S2MPS11_CLKS_NUM, GFP_KERNEL);
if (!clk_table)
return ERR_PTR(-ENOMEM);
for (i = 0; i < S2MPS11_CLKS_NUM; i++)
of_property_read_string_index(clk_np, "clock-output-names", i,
&s2mps11_clks_init[i].name);
return clk_np;
}
static int s2mps11_clk_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
struct device_node *clk_np = NULL;
int i, ret = 0;
u32 val;
s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
S2MPS11_CLKS_NUM, GFP_KERNEL);
if (!s2mps11_clks)
return -ENOMEM;
s2mps11_clk = s2mps11_clks;
clk_np = s2mps11_clk_parse_dt(pdev);
if (IS_ERR(clk_np))
return PTR_ERR(clk_np);
for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
s2mps11_clk->iodev = iodev;
s2mps11_clk->hw.init = &s2mps11_clks_init[i];
s2mps11_clk->mask = 1 << i;
ret = regmap_read(s2mps11_clk->iodev->regmap,
S2MPS11_REG_RTC_CTRL, &val);
if (ret < 0)
goto err_reg;
s2mps11_clk->enabled = val & s2mps11_clk->mask;
s2mps11_clk->clk = devm_clk_register(&pdev->dev,
&s2mps11_clk->hw);
if (IS_ERR(s2mps11_clk->clk)) {
dev_err(&pdev->dev, "Fail to register : %s\n",
s2mps11_name(s2mps11_clk));
ret = PTR_ERR(s2mps11_clk->clk);
goto err_reg;
}
s2mps11_clk->lookup = devm_kzalloc(&pdev->dev,
sizeof(struct clk_lookup), GFP_KERNEL);
if (!s2mps11_clk->lookup) {
ret = -ENOMEM;
goto err_lup;
}
s2mps11_clk->lookup->con_id = s2mps11_name(s2mps11_clk);
s2mps11_clk->lookup->clk = s2mps11_clk->clk;
clkdev_add(s2mps11_clk->lookup);
}
if (clk_table) {
for (i = 0; i < S2MPS11_CLKS_NUM; i++)
clk_table[i] = s2mps11_clks[i].clk;
clk_data.clks = clk_table;
clk_data.clk_num = S2MPS11_CLKS_NUM;
of_clk_add_provider(clk_np, of_clk_src_onecell_get, &clk_data);
}
platform_set_drvdata(pdev, s2mps11_clks);
return ret;
err_lup:
devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
err_reg:
while (s2mps11_clk > s2mps11_clks) {
if (s2mps11_clk->lookup) {
clkdev_drop(s2mps11_clk->lookup);
devm_clk_unregister(&pdev->dev, s2mps11_clk->clk);
}
s2mps11_clk--;
}
return ret;
}
static int s2mps11_clk_remove(struct platform_device *pdev)
{
struct s2mps11_clk *s2mps11_clks = platform_get_drvdata(pdev);
int i;
for (i = 0; i < S2MPS11_CLKS_NUM; i++)
clkdev_drop(s2mps11_clks[i].lookup);
return 0;
}
static const struct platform_device_id s2mps11_clk_id[] = {
{ "s2mps11-clk", 0},
{ },
};
MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
static struct platform_driver s2mps11_clk_driver = {
.driver = {
.name = "s2mps11-clk",
.owner = THIS_MODULE,
},
.probe = s2mps11_clk_probe,
.remove = s2mps11_clk_remove,
.id_table = s2mps11_clk_id,
};
static int __init s2mps11_clk_init(void)
{
return platform_driver_register(&s2mps11_clk_driver);
}
subsys_initcall(s2mps11_clk_init);
static void __init s2mps11_clk_cleanup(void)
{
platform_driver_unregister(&s2mps11_clk_driver);
}
module_exit(s2mps11_clk_cleanup);
MODULE_DESCRIPTION("S2MPS11 Clock Driver");
MODULE_AUTHOR("Yadwinder Singh Brar <yadi.brar@samsung.com>");
MODULE_LICENSE("GPL");

View File

@ -746,7 +746,7 @@ struct u300_clock {
u16 clk_val;
};
struct u300_clock const __initconst u300_clk_lookup[] = {
static struct u300_clock const u300_clk_lookup[] __initconst = {
{
.type = U300_CLK_TYPE_REST,
.id = 3,
@ -1151,7 +1151,7 @@ static void __init of_u300_syscon_mclk_init(struct device_node *np)
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
static const __initconst struct of_device_id u300_clk_match[] = {
static const struct of_device_id u300_clk_match[] __initconst = {
{
.compatible = "fixed-clock",
.data = of_fixed_clk_setup,

View File

@ -31,7 +31,7 @@ struct wm831x_clk {
bool xtal_ena;
};
static int wm831x_xtal_is_enabled(struct clk_hw *hw)
static int wm831x_xtal_is_prepared(struct clk_hw *hw)
{
struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
xtal_hw);
@ -52,7 +52,7 @@ static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,
}
static const struct clk_ops wm831x_xtal_ops = {
.is_enabled = wm831x_xtal_is_enabled,
.is_prepared = wm831x_xtal_is_prepared,
.recalc_rate = wm831x_xtal_recalc_rate,
};
@ -73,7 +73,7 @@ static const unsigned long wm831x_fll_auto_rates[] = {
24576000,
};
static int wm831x_fll_is_enabled(struct clk_hw *hw)
static int wm831x_fll_is_prepared(struct clk_hw *hw)
{
struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
fll_hw);
@ -170,7 +170,7 @@ static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
return -EINVAL;
if (wm831x_fll_is_enabled(hw))
if (wm831x_fll_is_prepared(hw))
return -EPERM;
return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
@ -220,7 +220,7 @@ static u8 wm831x_fll_get_parent(struct clk_hw *hw)
}
static const struct clk_ops wm831x_fll_ops = {
.is_enabled = wm831x_fll_is_enabled,
.is_prepared = wm831x_fll_is_prepared,
.prepare = wm831x_fll_prepare,
.unprepare = wm831x_fll_unprepare,
.round_rate = wm831x_fll_round_rate,
@ -237,7 +237,7 @@ static struct clk_init_data wm831x_fll_init = {
.flags = CLK_SET_RATE_GATE,
};
static int wm831x_clkout_is_enabled(struct clk_hw *hw)
static int wm831x_clkout_is_prepared(struct clk_hw *hw)
{
struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
clkout_hw);
@ -335,7 +335,7 @@ static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
}
static const struct clk_ops wm831x_clkout_ops = {
.is_enabled = wm831x_clkout_is_enabled,
.is_prepared = wm831x_clkout_is_prepared,
.prepare = wm831x_clkout_prepare,
.unprepare = wm831x_clkout_unprepare,
.get_parent = wm831x_clkout_get_parent,
@ -360,6 +360,8 @@ static int wm831x_clk_probe(struct platform_device *pdev)
if (!clkdata)
return -ENOMEM;
clkdata->wm831x = wm831x;
/* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
if (ret < 0) {

View File

@ -458,7 +458,6 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
clk->ops->unprepare(clk->hw);
}
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
/* caller must hold prepare_lock */
static void clk_disable_unused_subtree(struct clk *clk)
@ -559,6 +558,19 @@ struct clk *__clk_get_parent(struct clk *clk)
return !clk ? NULL : clk->parent;
}
struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
{
if (!clk || index >= clk->num_parents)
return NULL;
else if (!clk->parents)
return __clk_lookup(clk->parent_names[index]);
else if (!clk->parents[index])
return clk->parents[index] =
__clk_lookup(clk->parent_names[index]);
else
return clk->parents[index];
}
unsigned int __clk_get_enable_count(struct clk *clk)
{
return !clk ? 0 : clk->enable_count;
@ -594,6 +606,7 @@ unsigned long __clk_get_flags(struct clk *clk)
{
return !clk ? 0 : clk->flags;
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
bool __clk_is_prepared(struct clk *clk)
{
@ -679,6 +692,55 @@ struct clk *__clk_lookup(const char *name)
return NULL;
}
/*
* Helper for finding best parent to provide a given frequency. This can be used
* directly as a determine_rate callback (e.g. for a mux), or from a more
* complex clock that may combine a mux with other operations.
*/
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p)
{
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0;
/* if NO_REPARENT flag set, pass through to current parent */
if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
parent = clk->parent;
if (clk->flags & CLK_SET_RATE_PARENT)
best = __clk_round_rate(parent, rate);
else if (parent)
best = __clk_get_rate(parent);
else
best = __clk_get_rate(clk);
goto out;
}
/* find the parent that can provide the fastest rate <= rate */
num_parents = clk->num_parents;
for (i = 0; i < num_parents; i++) {
parent = clk_get_parent_by_index(clk, i);
if (!parent)
continue;
if (clk->flags & CLK_SET_RATE_PARENT)
parent_rate = __clk_round_rate(parent, rate);
else
parent_rate = __clk_get_rate(parent);
if (parent_rate <= rate && parent_rate > best) {
best_parent = parent;
best = parent_rate;
}
}
out:
if (best_parent)
*best_parent_p = best_parent;
*best_parent_rate = best;
return best;
}
/*** clk api ***/
void __clk_unprepare(struct clk *clk)
@ -702,7 +764,7 @@ void __clk_unprepare(struct clk *clk)
/**
* clk_unprepare - undo preparation of a clock source
* @clk: the clk being unprepare
* @clk: the clk being unprepared
*
* clk_unprepare may sleep, which differentiates it from clk_disable. In a
* simple case, clk_unprepare can be used instead of clk_disable to gate a clk
@ -869,27 +931,31 @@ EXPORT_SYMBOL_GPL(clk_enable);
/**
* __clk_round_rate - round the given rate for a clk
* @clk: round the rate of this clock
* @rate: the rate which is to be rounded
*
* Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
*/
unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = 0;
struct clk *parent;
if (!clk)
return 0;
if (!clk->ops->round_rate) {
if (clk->flags & CLK_SET_RATE_PARENT)
return __clk_round_rate(clk->parent, rate);
else
return clk->rate;
}
parent = clk->parent;
if (parent)
parent_rate = parent->rate;
if (clk->parent)
parent_rate = clk->parent->rate;
return clk->ops->round_rate(clk->hw, rate, &parent_rate);
if (clk->ops->determine_rate)
return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
&parent);
else if (clk->ops->round_rate)
return clk->ops->round_rate(clk->hw, rate, &parent_rate);
else if (clk->flags & CLK_SET_RATE_PARENT)
return __clk_round_rate(clk->parent, rate);
else
return clk->rate;
}
/**
@ -956,7 +1022,7 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
*
* Walks the subtree of clks starting with clk and recalculates rates as it
* goes. Note that if a clk does not implement the .recalc_rate callback then
* it is assumed that the clock will take on the rate of it's parent.
* it is assumed that the clock will take on the rate of its parent.
*
* clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
* if necessary.
@ -1014,6 +1080,115 @@ unsigned long clk_get_rate(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_get_rate);
static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent)
{
u8 i;
if (!clk->parents)
clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
GFP_KERNEL);
/*
* find index of new parent clock using cached parent ptrs,
* or if not yet cached, use string name comparison and cache
* them now to avoid future calls to __clk_lookup.
*/
for (i = 0; i < clk->num_parents; i++) {
if (clk->parents && clk->parents[i] == parent)
break;
else if (!strcmp(clk->parent_names[i], parent->name)) {
if (clk->parents)
clk->parents[i] = __clk_lookup(parent->name);
break;
}
}
return i;
}
static void clk_reparent(struct clk *clk, struct clk *new_parent)
{
hlist_del(&clk->child_node);
if (new_parent) {
/* avoid duplicate POST_RATE_CHANGE notifications */
if (new_parent->new_child == clk)
new_parent->new_child = NULL;
hlist_add_head(&clk->child_node, &new_parent->children);
} else {
hlist_add_head(&clk->child_node, &clk_orphan_list);
}
clk->parent = new_parent;
}
static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
{
unsigned long flags;
int ret = 0;
struct clk *old_parent = clk->parent;
/*
* Migrate prepare state between parents and prevent race with
* clk_enable().
*
* If the clock is not prepared, then a race with
* clk_enable/disable() is impossible since we already have the
* prepare lock (future calls to clk_enable() need to be preceded by
* a clk_prepare()).
*
* If the clock is prepared, migrate the prepared state to the new
* parent and also protect against a race with clk_enable() by
* forcing the clock and the new parent on. This ensures that all
* future calls to clk_enable() are practically NOPs with respect to
* hardware and software states.
*
* See also: Comment for clk_set_parent() below.
*/
if (clk->prepare_count) {
__clk_prepare(parent);
clk_enable(parent);
clk_enable(clk);
}
/* update the clk tree topology */
flags = clk_enable_lock();
clk_reparent(clk, parent);
clk_enable_unlock(flags);
/* change clock input source */
if (parent && clk->ops->set_parent)
ret = clk->ops->set_parent(clk->hw, p_index);
if (ret) {
flags = clk_enable_lock();
clk_reparent(clk, old_parent);
clk_enable_unlock(flags);
if (clk->prepare_count) {
clk_disable(clk);
clk_disable(parent);
__clk_unprepare(parent);
}
return ret;
}
/*
* Finish the migration of prepare state and undo the changes done
* for preventing a race with clk_enable().
*/
if (clk->prepare_count) {
clk_disable(clk);
clk_disable(old_parent);
__clk_unprepare(old_parent);
}
/* update debugfs with new clk tree topology */
clk_debug_reparent(clk, parent);
return 0;
}
/**
* __clk_speculate_rates
* @clk: first clk in the subtree
@ -1026,7 +1201,7 @@ EXPORT_SYMBOL_GPL(clk_get_rate);
* pre-rate change notifications and returns early if no clks in the
* subtree have subscribed to the notifications. Note that if a clk does not
* implement the .recalc_rate callback then it is assumed that the clock will
* take on the rate of it's parent.
* take on the rate of its parent.
*
* Caller must hold prepare_lock.
*/
@ -1058,18 +1233,25 @@ out:
return ret;
}
static void clk_calc_subtree(struct clk *clk, unsigned long new_rate)
static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
struct clk *new_parent, u8 p_index)
{
struct clk *child;
clk->new_rate = new_rate;
clk->new_parent = new_parent;
clk->new_parent_index = p_index;
/* include clk in new parent's PRE_RATE_CHANGE notifications */
clk->new_child = NULL;
if (new_parent && new_parent != clk->parent)
new_parent->new_child = clk;
hlist_for_each_entry(child, &clk->children, child_node) {
if (child->ops->recalc_rate)
child->new_rate = child->ops->recalc_rate(child->hw, new_rate);
else
child->new_rate = new_rate;
clk_calc_subtree(child, child->new_rate);
clk_calc_subtree(child, child->new_rate, NULL, 0);
}
}
@ -1080,50 +1262,63 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate)
static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
{
struct clk *top = clk;
struct clk *old_parent, *parent;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
u8 p_index = 0;
/* sanity */
if (IS_ERR_OR_NULL(clk))
return NULL;
/* save parent rate, if it exists */
if (clk->parent)
best_parent_rate = clk->parent->rate;
parent = old_parent = clk->parent;
if (parent)
best_parent_rate = parent->rate;
/* never propagate up to the parent */
if (!(clk->flags & CLK_SET_RATE_PARENT)) {
if (!clk->ops->round_rate) {
clk->new_rate = clk->rate;
return NULL;
}
new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate);
/* find the closest rate and parent clk/rate */
if (clk->ops->determine_rate) {
new_rate = clk->ops->determine_rate(clk->hw, rate,
&best_parent_rate,
&parent);
} else if (clk->ops->round_rate) {
new_rate = clk->ops->round_rate(clk->hw, rate,
&best_parent_rate);
} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
/* pass-through clock without adjustable parent */
clk->new_rate = clk->rate;
return NULL;
} else {
/* pass-through clock with adjustable parent */
top = clk_calc_new_rates(parent, rate);
new_rate = parent->new_rate;
goto out;
}
/* need clk->parent from here on out */
if (!clk->parent) {
pr_debug("%s: %s has NULL parent\n", __func__, clk->name);
/* some clocks must be gated to change parent */
if (parent != old_parent &&
(clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
pr_debug("%s: %s not gated but wants to reparent\n",
__func__, clk->name);
return NULL;
}
if (!clk->ops->round_rate) {
top = clk_calc_new_rates(clk->parent, rate);
new_rate = clk->parent->new_rate;
goto out;
/* try finding the new parent index */
if (parent) {
p_index = clk_fetch_parent_index(clk, parent);
if (p_index == clk->num_parents) {
pr_debug("%s: clk %s can not be parent of clk %s\n",
__func__, parent->name, clk->name);
return NULL;
}
}
new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate);
if (best_parent_rate != clk->parent->rate) {
top = clk_calc_new_rates(clk->parent, best_parent_rate);
goto out;
}
if ((clk->flags & CLK_SET_RATE_PARENT) && parent &&
best_parent_rate != parent->rate)
top = clk_calc_new_rates(parent, best_parent_rate);
out:
clk_calc_subtree(clk, new_rate);
clk_calc_subtree(clk, new_rate, parent, p_index);
return top;
}
@ -1135,7 +1330,7 @@ out:
*/
static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
{
struct clk *child, *fail_clk = NULL;
struct clk *child, *tmp_clk, *fail_clk = NULL;
int ret = NOTIFY_DONE;
if (clk->rate == clk->new_rate)
@ -1148,9 +1343,19 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
}
hlist_for_each_entry(child, &clk->children, child_node) {
clk = clk_propagate_rate_change(child, event);
if (clk)
fail_clk = clk;
/* Skip children who will be reparented to another clock */
if (child->new_parent && child->new_parent != clk)
continue;
tmp_clk = clk_propagate_rate_change(child, event);
if (tmp_clk)
fail_clk = tmp_clk;
}
/* handle the new child who might not be in clk->children yet */
if (clk->new_child) {
tmp_clk = clk_propagate_rate_change(clk->new_child, event);
if (tmp_clk)
fail_clk = tmp_clk;
}
return fail_clk;
@ -1168,6 +1373,10 @@ static void clk_change_rate(struct clk *clk)
old_rate = clk->rate;
/* set parent */
if (clk->new_parent && clk->new_parent != clk->parent)
__clk_set_parent(clk, clk->new_parent, clk->new_parent_index);
if (clk->parent)
best_parent_rate = clk->parent->rate;
@ -1182,8 +1391,16 @@ static void clk_change_rate(struct clk *clk)
if (clk->notifier_count && old_rate != clk->rate)
__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
hlist_for_each_entry(child, &clk->children, child_node)
hlist_for_each_entry(child, &clk->children, child_node) {
/* Skip children who will be reparented to another clock */
if (child->new_parent && child->new_parent != clk)
continue;
clk_change_rate(child);
}
/* handle the new child who might not be in clk->children yet */
if (clk->new_child)
clk_change_rate(clk->new_child);
}
/**
@ -1198,7 +1415,7 @@ static void clk_change_rate(struct clk *clk)
* outcome of clk's .round_rate implementation. If *parent_rate is unchanged
* after calling .round_rate then upstream parent propagation is ignored. If
* *parent_rate comes back with a new rate for clk's parent then we propagate
* up to clk's parent and set it's rate. Upward propagation will continue
* up to clk's parent and set its rate. Upward propagation will continue
* until either a clk does not support the CLK_SET_RATE_PARENT flag or
* .round_rate stops requesting changes to clk's parent_rate.
*
@ -1212,6 +1429,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
struct clk *top, *fail_clk;
int ret = 0;
if (!clk)
return 0;
/* prevent racing with updates to the clock topology */
clk_prepare_lock();
@ -1315,30 +1535,12 @@ static struct clk *__clk_init_parent(struct clk *clk)
kzalloc((sizeof(struct clk*) * clk->num_parents),
GFP_KERNEL);
if (!clk->parents)
ret = __clk_lookup(clk->parent_names[index]);
else if (!clk->parents[index])
ret = clk->parents[index] =
__clk_lookup(clk->parent_names[index]);
else
ret = clk->parents[index];
ret = clk_get_parent_by_index(clk, index);
out:
return ret;
}
static void clk_reparent(struct clk *clk, struct clk *new_parent)
{
hlist_del(&clk->child_node);
if (new_parent)
hlist_add_head(&clk->child_node, &new_parent->children);
else
hlist_add_head(&clk->child_node, &clk_orphan_list);
clk->parent = new_parent;
}
void __clk_reparent(struct clk *clk, struct clk *new_parent)
{
clk_reparent(clk, new_parent);
@ -1346,98 +1548,6 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent)
__clk_recalc_rates(clk, POST_RATE_CHANGE);
}
static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent)
{
u8 i;
if (!clk->parents)
clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
GFP_KERNEL);
/*
* find index of new parent clock using cached parent ptrs,
* or if not yet cached, use string name comparison and cache
* them now to avoid future calls to __clk_lookup.
*/
for (i = 0; i < clk->num_parents; i++) {
if (clk->parents && clk->parents[i] == parent)
break;
else if (!strcmp(clk->parent_names[i], parent->name)) {
if (clk->parents)
clk->parents[i] = __clk_lookup(parent->name);
break;
}
}
return i;
}
static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
{
unsigned long flags;
int ret = 0;
struct clk *old_parent = clk->parent;
/*
* Migrate prepare state between parents and prevent race with
* clk_enable().
*
* If the clock is not prepared, then a race with
* clk_enable/disable() is impossible since we already have the
* prepare lock (future calls to clk_enable() need to be preceded by
* a clk_prepare()).
*
* If the clock is prepared, migrate the prepared state to the new
* parent and also protect against a race with clk_enable() by
* forcing the clock and the new parent on. This ensures that all
* future calls to clk_enable() are practically NOPs with respect to
* hardware and software states.
*
* See also: Comment for clk_set_parent() below.
*/
if (clk->prepare_count) {
__clk_prepare(parent);
clk_enable(parent);
clk_enable(clk);
}
/* update the clk tree topology */
flags = clk_enable_lock();
clk_reparent(clk, parent);
clk_enable_unlock(flags);
/* change clock input source */
if (parent && clk->ops->set_parent)
ret = clk->ops->set_parent(clk->hw, p_index);
if (ret) {
flags = clk_enable_lock();
clk_reparent(clk, old_parent);
clk_enable_unlock(flags);
if (clk->prepare_count) {
clk_disable(clk);
clk_disable(parent);
__clk_unprepare(parent);
}
return ret;
}
/*
* Finish the migration of prepare state and undo the changes done
* for preventing a race with clk_enable().
*/
if (clk->prepare_count) {
clk_disable(clk);
clk_disable(old_parent);
__clk_unprepare(old_parent);
}
/* update debugfs with new clk tree topology */
clk_debug_reparent(clk, parent);
return 0;
}
/**
* clk_set_parent - switch the parent of a mux clk
* @clk: the mux clk whose input we are switching
@ -1461,7 +1571,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
u8 p_index = 0;
unsigned long p_rate = 0;
if (!clk || !clk->ops)
if (!clk)
return 0;
if (!clk->ops)
return -EINVAL;
/* verify ops for for multi-parent clks */
@ -1544,8 +1657,9 @@ int __clk_init(struct device *dev, struct clk *clk)
/* check that clk_ops are sane. See Documentation/clk.txt */
if (clk->ops->set_rate &&
!(clk->ops->round_rate && clk->ops->recalc_rate)) {
pr_warning("%s: %s must implement .round_rate & .recalc_rate\n",
!((clk->ops->round_rate || clk->ops->determine_rate) &&
clk->ops->recalc_rate)) {
pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n",
__func__, clk->name);
ret = -EINVAL;
goto out;
@ -1628,7 +1742,7 @@ int __clk_init(struct device *dev, struct clk *clk)
* this clock
*/
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
if (orphan->ops->get_parent) {
if (orphan->num_parents && orphan->ops->get_parent) {
i = orphan->ops->get_parent(orphan->hw);
if (!strcmp(clk->name, orphan->parent_names[i]))
__clk_reparent(orphan, clk);
@ -1648,7 +1762,7 @@ int __clk_init(struct device *dev, struct clk *clk)
* The .init callback is not used by any of the basic clock types, but
* exists for weird hardware that must perform initialization magic.
* Please consider other ways of solving initialization problems before
* using this callback, as it's use is discouraged.
* using this callback, as its use is discouraged.
*/
if (clk->ops->init)
clk->ops->init(clk->hw);
@ -1675,7 +1789,7 @@ out:
* very large numbers of clocks that need to be statically initialized. It is
* a layering violation to include clk-private.h from any code which implements
* a clock's .ops; as such any statically initialized clock data MUST be in a
* separate C file from the logic that implements it's operations. Returns 0
* separate C file from the logic that implements its operations. Returns 0
* on success, otherwise an error code.
*/
struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
@ -2115,13 +2229,13 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
*/
void __init of_clk_init(const struct of_device_id *matches)
{
const struct of_device_id *match;
struct device_node *np;
if (!matches)
matches = __clk_of_table;
for_each_matching_node(np, matches) {
const struct of_device_id *match = of_match_node(matches, np);
for_each_matching_node_and_match(np, matches, &match) {
of_clk_init_cb_t clk_init_cb = match->data;
clk_init_cb(np);
}

View File

@ -248,7 +248,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp2-pwm.3");
clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
clk_set_parent(clk, vctcxo);
clk_register_clkdev(clk, "uart_mux.0", NULL);
@ -258,7 +259,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
clk_set_parent(clk, vctcxo);
clk_register_clkdev(clk, "uart_mux.1", NULL);
@ -268,7 +270,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART2, 4, 3, 0, &clk_lock);
clk_set_parent(clk, vctcxo);
clk_register_clkdev(clk, "uart_mux.2", NULL);
@ -278,7 +281,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
clk = clk_register_mux(NULL, "uart3_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART3, 4, 3, 0, &clk_lock);
clk_set_parent(clk, vctcxo);
clk_register_clkdev(clk, "uart_mux.3", NULL);
@ -288,7 +292,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.3");
clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "uart_mux.0", NULL);
@ -297,7 +302,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.0");
clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.1", NULL);
@ -306,7 +312,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.1");
clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.2", NULL);
@ -315,7 +322,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.2");
clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.3", NULL);
@ -324,7 +332,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.3");
clk = clk_register_mux(NULL, "sdh_mux", sdh_parent,
ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(sdh_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_SDH0, 8, 2, 0, &clk_lock);
clk_register_clkdev(clk, "sdh_mux", NULL);
@ -354,7 +363,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, "usb_clk", NULL);
clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(disp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_DISP0, 6, 2, 0, &clk_lock);
clk_register_clkdev(clk, "disp_mux.0", NULL);
@ -376,7 +386,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, "disp_sphy.0", NULL);
clk = clk_register_mux(NULL, "disp1_mux", disp_parent,
ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(disp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_DISP1, 6, 2, 0, &clk_lock);
clk_register_clkdev(clk, "disp_mux.1", NULL);
@ -394,7 +405,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, "ccic_arbiter", NULL);
clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ccic_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_CCIC0, 6, 2, 0, &clk_lock);
clk_register_clkdev(clk, "ccic_mux.0", NULL);
@ -421,7 +433,8 @@ void __init mmp2_clk_init(void)
clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
clk = clk_register_mux(NULL, "ccic1_mux", ccic_parent,
ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ccic_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_CCIC1, 6, 2, 0, &clk_lock);
clk_register_clkdev(clk, "ccic_mux.1", NULL);

View File

@ -199,7 +199,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa168-pwm.3");
clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
clk_set_parent(clk, uart_pll);
clk_register_clkdev(clk, "uart_mux.0", NULL);
@ -209,7 +210,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
clk_set_parent(clk, uart_pll);
clk_register_clkdev(clk, "uart_mux.1", NULL);
@ -219,7 +221,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART2, 4, 3, 0, &clk_lock);
clk_set_parent(clk, uart_pll);
clk_register_clkdev(clk, "uart_mux.2", NULL);
@ -229,7 +232,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "uart_mux.0", NULL);
@ -238,7 +242,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.0");
clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.1", NULL);
@ -247,7 +252,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.1");
clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.2", NULL);
@ -256,7 +262,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.2");
clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.3", NULL);
@ -265,7 +272,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.3");
clk = clk_register_mux(NULL, "ssp4_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP4, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.4", NULL);
@ -278,7 +286,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(sdh_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "sdh0_mux", NULL);
@ -287,7 +296,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(sdh_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "sdh1_mux", NULL);
@ -304,7 +314,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, "sph_clk", NULL);
clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(disp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "disp_mux.0", NULL);
@ -317,7 +328,8 @@ void __init pxa168_clk_init(void)
clk_register_clkdev(clk, "hclk", "mmp-disp.0");
clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ccic_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "ccic_mux.0", NULL);
@ -327,8 +339,8 @@ void __init pxa168_clk_init(void)
clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
ARRAY_SIZE(ccic_phy_parent),
CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
7, 1, 0, &clk_lock);
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_CCIC0, 7, 1, 0, &clk_lock);
clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",

View File

@ -204,7 +204,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa910-pwm.3");
clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
clk_set_parent(clk, uart_pll);
clk_register_clkdev(clk, "uart_mux.0", NULL);
@ -214,7 +215,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
clk_set_parent(clk, uart_pll);
clk_register_clkdev(clk, "uart_mux.1", NULL);
@ -224,7 +226,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbcp_base + APBCP_UART2, 4, 3, 0, &clk_lock);
clk_set_parent(clk, uart_pll);
clk_register_clkdev(clk, "uart_mux.2", NULL);
@ -234,7 +237,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "uart_mux.0", NULL);
@ -243,7 +247,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-ssp.0");
clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ssp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
clk_register_clkdev(clk, "ssp_mux.1", NULL);
@ -256,7 +261,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(sdh_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "sdh0_mux", NULL);
@ -265,7 +271,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(sdh_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "sdh1_mux", NULL);
@ -282,7 +289,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, "sph_clk", NULL);
clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(disp_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "disp_mux.0", NULL);
@ -291,7 +299,8 @@ void __init pxa910_clk_init(void)
clk_register_clkdev(clk, NULL, "mmp-disp.0");
clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
ARRAY_SIZE(ccic_parent),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
clk_register_clkdev(clk, "ccic_mux.0", NULL);
@ -301,8 +310,8 @@ void __init pxa910_clk_init(void)
clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
ARRAY_SIZE(ccic_phy_parent),
CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
7, 1, 0, &clk_lock);
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
apmu_base + APMU_CCIC0, 7, 1, 0, &clk_lock);
clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",

View File

@ -32,13 +32,13 @@
enum { A370_CPU_TO_NBCLK, A370_CPU_TO_HCLK, A370_CPU_TO_DRAMCLK };
static const struct coreclk_ratio __initconst a370_coreclk_ratios[] = {
static const struct coreclk_ratio a370_coreclk_ratios[] __initconst = {
{ .id = A370_CPU_TO_NBCLK, .name = "nbclk" },
{ .id = A370_CPU_TO_HCLK, .name = "hclk" },
{ .id = A370_CPU_TO_DRAMCLK, .name = "dramclk" },
};
static const u32 __initconst a370_tclk_freqs[] = {
static const u32 a370_tclk_freqs[] __initconst = {
16600000,
20000000,
};
@ -52,7 +52,7 @@ static u32 __init a370_get_tclk_freq(void __iomem *sar)
return a370_tclk_freqs[tclk_freq_select];
}
static const u32 __initconst a370_cpu_freqs[] = {
static const u32 a370_cpu_freqs[] __initconst = {
400000000,
533000000,
667000000,
@ -78,7 +78,7 @@ static u32 __init a370_get_cpu_freq(void __iomem *sar)
return cpu_freq;
}
static const int __initconst a370_nbclk_ratios[32][2] = {
static const int a370_nbclk_ratios[32][2] __initconst = {
{0, 1}, {1, 2}, {2, 2}, {2, 2},
{1, 2}, {1, 2}, {1, 1}, {2, 3},
{0, 1}, {1, 2}, {2, 4}, {0, 1},
@ -89,7 +89,7 @@ static const int __initconst a370_nbclk_ratios[32][2] = {
{0, 1}, {0, 1}, {0, 1}, {0, 1},
};
static const int __initconst a370_hclk_ratios[32][2] = {
static const int a370_hclk_ratios[32][2] __initconst = {
{0, 1}, {1, 2}, {2, 6}, {2, 3},
{1, 3}, {1, 4}, {1, 2}, {2, 6},
{0, 1}, {1, 6}, {2, 10}, {0, 1},
@ -100,7 +100,7 @@ static const int __initconst a370_hclk_ratios[32][2] = {
{0, 1}, {0, 1}, {0, 1}, {0, 1},
};
static const int __initconst a370_dramclk_ratios[32][2] = {
static const int a370_dramclk_ratios[32][2] __initconst = {
{0, 1}, {1, 2}, {2, 3}, {2, 3},
{1, 3}, {1, 2}, {1, 2}, {2, 6},
{0, 1}, {1, 3}, {2, 5}, {0, 1},
@ -152,7 +152,7 @@ CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock",
* Clock Gating Control
*/
static const struct clk_gating_soc_desc __initconst a370_gating_desc[] = {
static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
{ "audio", NULL, 0, 0 },
{ "pex0_en", NULL, 1, 0 },
{ "pex1_en", NULL, 2, 0 },

View File

@ -40,7 +40,7 @@
enum { AXP_CPU_TO_NBCLK, AXP_CPU_TO_HCLK, AXP_CPU_TO_DRAMCLK };
static const struct coreclk_ratio __initconst axp_coreclk_ratios[] = {
static const struct coreclk_ratio axp_coreclk_ratios[] __initconst = {
{ .id = AXP_CPU_TO_NBCLK, .name = "nbclk" },
{ .id = AXP_CPU_TO_HCLK, .name = "hclk" },
{ .id = AXP_CPU_TO_DRAMCLK, .name = "dramclk" },
@ -52,7 +52,7 @@ static u32 __init axp_get_tclk_freq(void __iomem *sar)
return 250000000;
}
static const u32 __initconst axp_cpu_freqs[] = {
static const u32 axp_cpu_freqs[] __initconst = {
1000000000,
1066000000,
1200000000,
@ -89,7 +89,7 @@ static u32 __init axp_get_cpu_freq(void __iomem *sar)
return cpu_freq;
}
static const int __initconst axp_nbclk_ratios[32][2] = {
static const int axp_nbclk_ratios[32][2] __initconst = {
{0, 1}, {1, 2}, {2, 2}, {2, 2},
{1, 2}, {1, 2}, {1, 1}, {2, 3},
{0, 1}, {1, 2}, {2, 4}, {0, 1},
@ -100,7 +100,7 @@ static const int __initconst axp_nbclk_ratios[32][2] = {
{0, 1}, {0, 1}, {0, 1}, {0, 1},
};
static const int __initconst axp_hclk_ratios[32][2] = {
static const int axp_hclk_ratios[32][2] __initconst = {
{0, 1}, {1, 2}, {2, 6}, {2, 3},
{1, 3}, {1, 4}, {1, 2}, {2, 6},
{0, 1}, {1, 6}, {2, 10}, {0, 1},
@ -111,7 +111,7 @@ static const int __initconst axp_hclk_ratios[32][2] = {
{0, 1}, {0, 1}, {0, 1}, {0, 1},
};
static const int __initconst axp_dramclk_ratios[32][2] = {
static const int axp_dramclk_ratios[32][2] __initconst = {
{0, 1}, {1, 2}, {2, 3}, {2, 3},
{1, 3}, {1, 2}, {1, 2}, {2, 6},
{0, 1}, {1, 3}, {2, 5}, {0, 1},
@ -169,7 +169,7 @@ CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock",
* Clock Gating Control
*/
static const struct clk_gating_soc_desc __initconst axp_gating_desc[] = {
static const struct clk_gating_soc_desc axp_gating_desc[] __initconst = {
{ "audio", NULL, 0, 0 },
{ "ge3", NULL, 1, 0 },
{ "ge2", NULL, 2, 0 },

View File

@ -119,7 +119,7 @@ void __init of_cpu_clk_setup(struct device_node *node)
cpuclk = kzalloc(ncpus * sizeof(*cpuclk), GFP_KERNEL);
if (WARN_ON(!cpuclk))
return;
goto cpuclk_out;
clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
if (WARN_ON(!clks))
@ -170,6 +170,8 @@ bail_out:
kfree(cpuclk[ncpus].clk_name);
clks_out:
kfree(cpuclk);
cpuclk_out:
iounmap(clock_complex_base);
}
CLK_OF_DECLARE(armada_xp_cpu_clock, "marvell,armada-xp-cpu-clock",

View File

@ -45,8 +45,10 @@ void __init mvebu_coreclk_setup(struct device_node *np,
clk_data.clk_num = 2 + desc->num_ratios;
clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
GFP_KERNEL);
if (WARN_ON(!clk_data.clks))
if (WARN_ON(!clk_data.clks)) {
iounmap(base);
return;
}
/* Register TCLK */
of_property_read_string_index(np, "clock-output-names", 0,
@ -134,7 +136,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (WARN_ON(!ctrl))
return;
goto ctrl_out;
spin_lock_init(&ctrl->lock);
@ -145,10 +147,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
ctrl->num_gates = n;
ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
GFP_KERNEL);
if (WARN_ON(!ctrl->gates)) {
kfree(ctrl);
return;
}
if (WARN_ON(!ctrl->gates))
goto gates_out;
for (n = 0; n < ctrl->num_gates; n++) {
const char *parent =
@ -160,4 +160,10 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
}
of_clk_add_provider(np, clk_gating_get_src, ctrl);
return;
gates_out:
kfree(ctrl);
ctrl_out:
iounmap(base);
}

View File

@ -74,12 +74,12 @@
enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
static const struct coreclk_ratio __initconst dove_coreclk_ratios[] = {
static const struct coreclk_ratio dove_coreclk_ratios[] __initconst = {
{ .id = DOVE_CPU_TO_L2, .name = "l2clk", },
{ .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
};
static const u32 __initconst dove_tclk_freqs[] = {
static const u32 dove_tclk_freqs[] __initconst = {
166666667,
125000000,
0, 0
@ -92,7 +92,7 @@ static u32 __init dove_get_tclk_freq(void __iomem *sar)
return dove_tclk_freqs[opt];
}
static const u32 __initconst dove_cpu_freqs[] = {
static const u32 dove_cpu_freqs[] __initconst = {
0, 0, 0, 0, 0,
1000000000,
933333333, 933333333,
@ -111,12 +111,12 @@ static u32 __init dove_get_cpu_freq(void __iomem *sar)
return dove_cpu_freqs[opt];
}
static const int __initconst dove_cpu_l2_ratios[8][2] = {
static const int dove_cpu_l2_ratios[8][2] __initconst = {
{ 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
{ 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
};
static const int __initconst dove_cpu_ddr_ratios[16][2] = {
static const int dove_cpu_ddr_ratios[16][2] __initconst = {
{ 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
{ 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
{ 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
@ -164,7 +164,7 @@ CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init);
* Clock Gating Control
*/
static const struct clk_gating_soc_desc __initconst dove_gating_desc[] = {
static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = {
{ "usb0", NULL, 0, 0 },
{ "usb1", NULL, 1, 0 },
{ "ge", "gephy", 2, 0 },

View File

@ -78,7 +78,7 @@
enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
static const struct coreclk_ratio __initconst kirkwood_coreclk_ratios[] = {
static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = {
{ .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
{ .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
};
@ -90,7 +90,7 @@ static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
return (opt) ? 166666667 : 200000000;
}
static const u32 __initconst kirkwood_cpu_freqs[] = {
static const u32 kirkwood_cpu_freqs[] __initconst = {
0, 0, 0, 0,
600000000,
0,
@ -111,12 +111,12 @@ static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
return kirkwood_cpu_freqs[opt];
}
static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
static const int kirkwood_cpu_l2_ratios[8][2] __initconst = {
{ 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
{ 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
};
static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = {
{ 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
{ 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
{ 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
@ -145,7 +145,7 @@ static void __init kirkwood_get_clk_ratio(
}
}
static const u32 __initconst mv88f6180_cpu_freqs[] = {
static const u32 mv88f6180_cpu_freqs[] __initconst = {
0, 0, 0, 0, 0,
600000000,
800000000,
@ -158,7 +158,7 @@ static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
return mv88f6180_cpu_freqs[opt];
}
static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = {
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
{ 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
};
@ -219,7 +219,7 @@ CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock",
* Clock Gating Control
*/
static const struct clk_gating_soc_desc __initconst kirkwood_gating_desc[] = {
static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
{ "ge0", NULL, 0, 0 },
{ "pex0", NULL, 2, 0 },
{ "usb0", NULL, 3, 0 },

View File

@ -10,6 +10,7 @@
*/
#include <linux/clk.h>
#include <linux/clk/mxs.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/init.h>

View File

@ -52,8 +52,8 @@ static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parent_names, int num_parents)
{
return clk_register_mux(NULL, name, parent_names, num_parents,
CLK_SET_RATE_PARENT, reg, shift, width,
0, &mxs_lock);
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
reg, shift, width, 0, &mxs_lock);
}
static inline struct clk *mxs_clk_fixed_factor(const char *name,

View File

@ -8,3 +8,6 @@ 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
ifdef CONFIG_COMMON_CLK
obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
endif

View File

@ -62,7 +62,7 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = {
#endif /* CONFIG_PM_SLEEP */
/* register exynos_audss clocks */
void __init exynos_audss_clk_init(struct device_node *np)
static void __init exynos_audss_clk_init(struct device_node *np)
{
reg_base = of_iomap(np, 0);
if (!reg_base) {
@ -82,11 +82,13 @@ void __init exynos_audss_clk_init(struct device_node *np)
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
mout_audss_p, ARRAY_SIZE(mout_audss_p), 0,
mout_audss_p, ARRAY_SIZE(mout_audss_p),
CLK_SET_RATE_NO_REPARENT,
reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s",
mout_i2s_p, ARRAY_SIZE(mout_i2s_p), 0,
mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
CLK_SET_RATE_NO_REPARENT,
reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp",

View File

@ -17,7 +17,6 @@
#include <linux/of_address.h>
#include "clk.h"
#include "clk-pll.h"
/* Exynos4 clock controller register offsets */
#define SRC_LEFTBUS 0x4200
@ -97,12 +96,15 @@
#define GATE_IP_PERIL 0xc950
#define E4210_GATE_IP_PERIR 0xc960
#define GATE_BLOCK 0xc970
#define E4X12_MPLL_LOCK 0x10008
#define E4X12_MPLL_CON0 0x10108
#define SRC_DMC 0x10200
#define SRC_MASK_DMC 0x10300
#define DIV_DMC0 0x10500
#define DIV_DMC1 0x10504
#define GATE_IP_DMC 0x10900
#define APLL_LOCK 0x14000
#define E4210_MPLL_LOCK 0x14008
#define APLL_CON0 0x14100
#define E4210_MPLL_CON0 0x14108
#define SRC_CPU 0x14200
@ -121,6 +123,12 @@ enum exynos4_soc {
EXYNOS4X12,
};
/* list of PLLs to be registered */
enum exynos4_plls {
apll, mpll, epll, vpll,
nr_plls /* number of PLLs */
};
/*
* Let each supported clock get a unique id. This id is used to lookup the clock
* for device tree based platforms. The clocks are categorized into three
@ -169,7 +177,7 @@ enum exynos4_clks {
gicisp, smmu_isp, smmu_drc, smmu_fd, smmu_lite0, smmu_lite1, mcuctl_isp,
mpwm_isp, i2c0_isp, i2c1_isp, mtcadc_isp, pwm_isp, wdt_isp, uart_isp,
asyncaxim, smmu_ispcx, spi0_isp, spi1_isp, pwm_isp_sclk, spi0_isp_sclk,
spi1_isp_sclk, uart_isp_sclk,
spi1_isp_sclk, uart_isp_sclk, tmu_apbif,
/* mux clocks */
mout_fimc0 = 384, mout_fimc1, mout_fimc2, mout_fimc3, mout_cam0,
@ -187,7 +195,7 @@ enum exynos4_clks {
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static __initdata unsigned long exynos4210_clk_save[] = {
static unsigned long exynos4210_clk_save[] __initdata = {
E4210_SRC_IMAGE,
E4210_SRC_LCD1,
E4210_SRC_MASK_LCD1,
@ -198,7 +206,7 @@ static __initdata unsigned long exynos4210_clk_save[] = {
E4210_MPLL_CON0,
};
static __initdata unsigned long exynos4x12_clk_save[] = {
static unsigned long exynos4x12_clk_save[] __initdata = {
E4X12_GATE_IP_IMAGE,
E4X12_GATE_IP_PERIR,
E4X12_SRC_CAM1,
@ -207,7 +215,7 @@ static __initdata unsigned long exynos4x12_clk_save[] = {
E4X12_MPLL_CON0,
};
static __initdata unsigned long exynos4_clk_regs[] = {
static unsigned long exynos4_clk_regs[] __initdata = {
SRC_LEFTBUS,
DIV_LEFTBUS,
GATE_IP_LEFTBUS,
@ -338,24 +346,24 @@ PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
/* fixed rate clocks generated outside the soc */
struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0),
FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0),
};
/* fixed rate clocks generated inside the soc */
struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
};
struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
};
/* list of mux clocks supported in all exynos4 soc's */
struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
MUX_FA(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
CLK_SET_RATE_PARENT, 0, "mout_apll"),
MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
@ -367,17 +375,20 @@ struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
CLK_SET_RATE_PARENT, 0),
MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIL1, 8, 2),
MUX(none, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1),
MUX_A(sclk_epll, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1, "sclk_epll"),
MUX(sclk_epll, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1),
MUX(none, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1),
};
/* list of mux clocks supported in exynos4210 soc */
struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
static struct samsung_mux_clock exynos4210_mux_early[] __initdata = {
MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
};
static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
MUX(none, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1),
MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
MUX(none, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1),
MUX(none, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1),
MUX(none, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1),
@ -385,11 +396,9 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
MUX(none, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1),
MUX(none, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1, "mout_mpll"),
MUX_A(mout_core, "mout_core", mout_core_p4210,
SRC_CPU, 16, 1, "moutcore"),
MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210,
SRC_TOP0, 8, 1, "sclk_vpll"),
MUX(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
MUX(mout_core, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
MUX(sclk_vpll, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
MUX(mout_fimc1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
MUX(mout_fimc2, "mout_fimc2", group1_p4210, SRC_CAM, 8, 4),
@ -423,9 +432,9 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
};
/* list of mux clocks supported in exynos4x12 soc */
struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
SRC_CPU, 24, 1, "mout_mpll"),
static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
MUX(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
SRC_CPU, 24, 1),
MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
MUX(none, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
MUX(mout_mpll_user_t, "mout_mpll_user_t", mout_mpll_user_p4x12,
@ -445,12 +454,9 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
MUX(none, "mout_jpeg0", sclk_ampll_p4x12, E4X12_SRC_CAM1, 0, 1),
MUX(none, "mout_jpeg1", sclk_evpll_p, E4X12_SRC_CAM1, 4, 1),
MUX(none, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p,
SRC_DMC, 12, 1, "sclk_mpll"),
MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p,
SRC_TOP0, 8, 1, "sclk_vpll"),
MUX_A(mout_core, "mout_core", mout_core_p4x12,
SRC_CPU, 16, 1, "moutcore"),
MUX(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
MUX(sclk_vpll, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
MUX(mout_core, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
MUX(mout_fimc2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
@ -491,7 +497,7 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
};
/* list of divider clocks supported in all exynos4 soc's */
struct samsung_div_clock exynos4_div_clks[] __initdata = {
static struct samsung_div_clock exynos4_div_clks[] __initdata = {
DIV(none, "div_core", "mout_core", DIV_CPU0, 0, 3),
DIV(none, "div_core2", "div_core", DIV_CPU0, 28, 3),
DIV(none, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
@ -538,9 +544,8 @@ struct samsung_div_clock exynos4_div_clks[] __initdata = {
DIV(none, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
DIV_A(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3, "armclk"),
DIV_A(sclk_apll, "sclk_apll", "mout_apll",
DIV_CPU0, 24, 3, "sclk_apll"),
DIV(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
DIV(sclk_apll, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
CLK_SET_RATE_PARENT, 0),
DIV_F(none, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
@ -554,7 +559,7 @@ struct samsung_div_clock exynos4_div_clks[] __initdata = {
};
/* list of divider clocks supported in exynos4210 soc */
struct samsung_div_clock exynos4210_div_clks[] __initdata = {
static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
DIV(aclk200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4),
DIV(none, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
@ -565,7 +570,7 @@ struct samsung_div_clock exynos4210_div_clks[] __initdata = {
};
/* list of divider clocks supported in exynos4x12 soc */
struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
DIV(none, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
@ -594,7 +599,7 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
};
/* list of gate clocks supported in all exynos4 soc's */
struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
/*
* After all Exynos4 based platforms are migrated to use device tree,
* the device name and clock alias names specified below for some
@ -629,164 +634,151 @@ struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
CLK_SET_RATE_PARENT, 0),
GATE(sclk_audio1, "sclk_audio1", "div_audio1", SRC_MASK_PERIL1, 0,
CLK_SET_RATE_PARENT, 0),
GATE_D(vp, "s5p-mixer", "vp", "aclk160", GATE_IP_TV, 0, 0, 0),
GATE_D(mixer, "s5p-mixer", "mixer", "aclk160", GATE_IP_TV, 1, 0, 0),
GATE_D(hdmi, "exynos4-hdmi", "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0),
GATE_A(pwm, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0, "timers"),
GATE_A(sdmmc4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0, "biu"),
GATE_A(usb_host, "usb_host", "aclk133",
GATE_IP_FSYS, 12, 0, 0, "usbhost"),
GATE_DA(sclk_fimc0, "exynos4-fimc.0", "sclk_fimc0", "div_fimc0",
SRC_MASK_CAM, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
GATE_DA(sclk_fimc1, "exynos4-fimc.1", "sclk_fimc1", "div_fimc1",
SRC_MASK_CAM, 4, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
GATE_DA(sclk_fimc2, "exynos4-fimc.2", "sclk_fimc2", "div_fimc2",
SRC_MASK_CAM, 8, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
GATE_DA(sclk_fimc3, "exynos4-fimc.3", "sclk_fimc3", "div_fimc3",
SRC_MASK_CAM, 12, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
GATE_DA(sclk_csis0, "s5p-mipi-csis.0", "sclk_csis0", "div_csis0",
SRC_MASK_CAM, 24, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
GATE_DA(sclk_csis1, "s5p-mipi-csis.1", "sclk_csis1", "div_csis1",
SRC_MASK_CAM, 28, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
GATE_DA(sclk_fimd0, "exynos4-fb.0", "sclk_fimd0", "div_fimd0",
SRC_MASK_LCD0, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
GATE_DA(sclk_mmc0, "exynos4-sdhci.0", "sclk_mmc0", "div_mmc_pre0",
SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0,
"mmc_busclk.2"),
GATE_DA(sclk_mmc1, "exynos4-sdhci.1", "sclk_mmc1", "div_mmc_pre1",
SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0,
"mmc_busclk.2"),
GATE_DA(sclk_mmc2, "exynos4-sdhci.2", "sclk_mmc2", "div_mmc_pre2",
SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0,
"mmc_busclk.2"),
GATE_DA(sclk_mmc3, "exynos4-sdhci.3", "sclk_mmc3", "div_mmc_pre3",
SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0,
"mmc_busclk.2"),
GATE_DA(sclk_mmc4, NULL, "sclk_mmc4", "div_mmc_pre4",
SRC_MASK_FSYS, 16, CLK_SET_RATE_PARENT, 0, "ciu"),
GATE_DA(sclk_uart0, "exynos4210-uart.0", "uclk0", "div_uart0",
SRC_MASK_PERIL0, 0, CLK_SET_RATE_PARENT,
0, "clk_uart_baud0"),
GATE_DA(sclk_uart1, "exynos4210-uart.1", "uclk1", "div_uart1",
SRC_MASK_PERIL0, 4, CLK_SET_RATE_PARENT,
0, "clk_uart_baud0"),
GATE_DA(sclk_uart2, "exynos4210-uart.2", "uclk2", "div_uart2",
SRC_MASK_PERIL0, 8, CLK_SET_RATE_PARENT,
0, "clk_uart_baud0"),
GATE_DA(sclk_uart3, "exynos4210-uart.3", "uclk3", "div_uart3",
SRC_MASK_PERIL0, 12, CLK_SET_RATE_PARENT,
0, "clk_uart_baud0"),
GATE_DA(sclk_uart4, "exynos4210-uart.4", "uclk4", "div_uart4",
SRC_MASK_PERIL0, 16, CLK_SET_RATE_PARENT,
0, "clk_uart_baud0"),
GATE(vp, "vp", "aclk160", GATE_IP_TV, 0, 0, 0),
GATE(mixer, "mixer", "aclk160", GATE_IP_TV, 1, 0, 0),
GATE(hdmi, "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0),
GATE(pwm, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0),
GATE(sdmmc4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0),
GATE(usb_host, "usb_host", "aclk133", GATE_IP_FSYS, 12, 0, 0),
GATE(sclk_fimc0, "sclk_fimc0", "div_fimc0", SRC_MASK_CAM, 0,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_fimc1, "sclk_fimc1", "div_fimc1", SRC_MASK_CAM, 4,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_fimc2, "sclk_fimc2", "div_fimc2", SRC_MASK_CAM, 8,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_fimc3, "sclk_fimc3", "div_fimc3", SRC_MASK_CAM, 12,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_csis0, "sclk_csis0", "div_csis0", SRC_MASK_CAM, 24,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_csis1, "sclk_csis1", "div_csis1", SRC_MASK_CAM, 28,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_fimd0, "sclk_fimd0", "div_fimd0", SRC_MASK_LCD0, 0,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_mmc0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_mmc1, "sclk_mmc1", "div_mmc_pre1", SRC_MASK_FSYS, 4,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_mmc2, "sclk_mmc2", "div_mmc_pre2", SRC_MASK_FSYS, 8,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_mmc3, "sclk_mmc3", "div_mmc_pre3", SRC_MASK_FSYS, 12,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_mmc4, "sclk_mmc4", "div_mmc_pre4", SRC_MASK_FSYS, 16,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_uart0, "uclk0", "div_uart0", SRC_MASK_PERIL0, 0,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_uart1, "uclk1", "div_uart1", SRC_MASK_PERIL0, 4,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_uart2, "uclk2", "div_uart2", SRC_MASK_PERIL0, 8,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_uart3, "uclk3", "div_uart3", SRC_MASK_PERIL0, 12,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_uart4, "uclk4", "div_uart4", SRC_MASK_PERIL0, 16,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_audio2, "sclk_audio2", "div_audio2", SRC_MASK_PERIL1, 4,
CLK_SET_RATE_PARENT, 0),
GATE_DA(sclk_spi0, "exynos4210-spi.0", "sclk_spi0", "div_spi_pre0",
SRC_MASK_PERIL1, 16, CLK_SET_RATE_PARENT,
0, "spi_busclk0"),
GATE_DA(sclk_spi1, "exynos4210-spi.1", "sclk_spi1", "div_spi_pre1",
SRC_MASK_PERIL1, 20, CLK_SET_RATE_PARENT,
0, "spi_busclk0"),
GATE_DA(sclk_spi2, "exynos4210-spi.2", "sclk_spi2", "div_spi_pre2",
SRC_MASK_PERIL1, 24, CLK_SET_RATE_PARENT,
0, "spi_busclk0"),
GATE_DA(fimc0, "exynos4-fimc.0", "fimc0", "aclk160",
GATE_IP_CAM, 0, 0, 0, "fimc"),
GATE_DA(fimc1, "exynos4-fimc.1", "fimc1", "aclk160",
GATE_IP_CAM, 1, 0, 0, "fimc"),
GATE_DA(fimc2, "exynos4-fimc.2", "fimc2", "aclk160",
GATE_IP_CAM, 2, 0, 0, "fimc"),
GATE_DA(fimc3, "exynos4-fimc.3", "fimc3", "aclk160",
GATE_IP_CAM, 3, 0, 0, "fimc"),
GATE_DA(csis0, "s5p-mipi-csis.0", "csis0", "aclk160",
GATE_IP_CAM, 4, 0, 0, "fimc"),
GATE_DA(csis1, "s5p-mipi-csis.1", "csis1", "aclk160",
GATE_IP_CAM, 5, 0, 0, "fimc"),
GATE_DA(smmu_fimc0, "exynos-sysmmu.5", "smmu_fimc0", "aclk160",
GATE_IP_CAM, 7, 0, 0, "sysmmu"),
GATE_DA(smmu_fimc1, "exynos-sysmmu.6", "smmu_fimc1", "aclk160",
GATE_IP_CAM, 8, 0, 0, "sysmmu"),
GATE_DA(smmu_fimc2, "exynos-sysmmu.7", "smmu_fimc2", "aclk160",
GATE_IP_CAM, 9, 0, 0, "sysmmu"),
GATE_DA(smmu_fimc3, "exynos-sysmmu.8", "smmu_fimc3", "aclk160",
GATE_IP_CAM, 10, 0, 0, "sysmmu"),
GATE_DA(smmu_jpeg, "exynos-sysmmu.3", "smmu_jpeg", "aclk160",
GATE_IP_CAM, 11, 0, 0, "sysmmu"),
GATE(sclk_spi0, "sclk_spi0", "div_spi_pre0", SRC_MASK_PERIL1, 16,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_spi1, "sclk_spi1", "div_spi_pre1", SRC_MASK_PERIL1, 20,
CLK_SET_RATE_PARENT, 0),
GATE(sclk_spi2, "sclk_spi2", "div_spi_pre2", SRC_MASK_PERIL1, 24,
CLK_SET_RATE_PARENT, 0),
GATE(fimc0, "fimc0", "aclk160", GATE_IP_CAM, 0,
0, 0),
GATE(fimc1, "fimc1", "aclk160", GATE_IP_CAM, 1,
0, 0),
GATE(fimc2, "fimc2", "aclk160", GATE_IP_CAM, 2,
0, 0),
GATE(fimc3, "fimc3", "aclk160", GATE_IP_CAM, 3,
0, 0),
GATE(csis0, "csis0", "aclk160", GATE_IP_CAM, 4,
0, 0),
GATE(csis1, "csis1", "aclk160", GATE_IP_CAM, 5,
0, 0),
GATE(smmu_fimc0, "smmu_fimc0", "aclk160", GATE_IP_CAM, 7,
0, 0),
GATE(smmu_fimc1, "smmu_fimc1", "aclk160", GATE_IP_CAM, 8,
0, 0),
GATE(smmu_fimc2, "smmu_fimc2", "aclk160", GATE_IP_CAM, 9,
0, 0),
GATE(smmu_fimc3, "smmu_fimc3", "aclk160", GATE_IP_CAM, 10,
0, 0),
GATE(smmu_jpeg, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11,
0, 0),
GATE(pixelasyncm0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0),
GATE(pixelasyncm1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0),
GATE_DA(smmu_tv, "exynos-sysmmu.2", "smmu_tv", "aclk160",
GATE_IP_TV, 4, 0, 0, "sysmmu"),
GATE_DA(mfc, "s5p-mfc", "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0, "mfc"),
GATE_DA(smmu_mfcl, "exynos-sysmmu.0", "smmu_mfcl", "aclk100",
GATE_IP_MFC, 1, 0, 0, "sysmmu"),
GATE_DA(smmu_mfcr, "exynos-sysmmu.1", "smmu_mfcr", "aclk100",
GATE_IP_MFC, 2, 0, 0, "sysmmu"),
GATE_DA(fimd0, "exynos4-fb.0", "fimd0", "aclk160",
GATE_IP_LCD0, 0, 0, 0, "fimd"),
GATE_DA(smmu_fimd0, "exynos-sysmmu.10", "smmu_fimd0", "aclk160",
GATE_IP_LCD0, 4, 0, 0, "sysmmu"),
GATE_DA(pdma0, "dma-pl330.0", "pdma0", "aclk133",
GATE_IP_FSYS, 0, 0, 0, "dma"),
GATE_DA(pdma1, "dma-pl330.1", "pdma1", "aclk133",
GATE_IP_FSYS, 1, 0, 0, "dma"),
GATE_DA(sdmmc0, "exynos4-sdhci.0", "sdmmc0", "aclk133",
GATE_IP_FSYS, 5, 0, 0, "hsmmc"),
GATE_DA(sdmmc1, "exynos4-sdhci.1", "sdmmc1", "aclk133",
GATE_IP_FSYS, 6, 0, 0, "hsmmc"),
GATE_DA(sdmmc2, "exynos4-sdhci.2", "sdmmc2", "aclk133",
GATE_IP_FSYS, 7, 0, 0, "hsmmc"),
GATE_DA(sdmmc3, "exynos4-sdhci.3", "sdmmc3", "aclk133",
GATE_IP_FSYS, 8, 0, 0, "hsmmc"),
GATE_DA(uart0, "exynos4210-uart.0", "uart0", "aclk100",
GATE_IP_PERIL, 0, 0, 0, "uart"),
GATE_DA(uart1, "exynos4210-uart.1", "uart1", "aclk100",
GATE_IP_PERIL, 1, 0, 0, "uart"),
GATE_DA(uart2, "exynos4210-uart.2", "uart2", "aclk100",
GATE_IP_PERIL, 2, 0, 0, "uart"),
GATE_DA(uart3, "exynos4210-uart.3", "uart3", "aclk100",
GATE_IP_PERIL, 3, 0, 0, "uart"),
GATE_DA(uart4, "exynos4210-uart.4", "uart4", "aclk100",
GATE_IP_PERIL, 4, 0, 0, "uart"),
GATE_DA(i2c0, "s3c2440-i2c.0", "i2c0", "aclk100",
GATE_IP_PERIL, 6, 0, 0, "i2c"),
GATE_DA(i2c1, "s3c2440-i2c.1", "i2c1", "aclk100",
GATE_IP_PERIL, 7, 0, 0, "i2c"),
GATE_DA(i2c2, "s3c2440-i2c.2", "i2c2", "aclk100",
GATE_IP_PERIL, 8, 0, 0, "i2c"),
GATE_DA(i2c3, "s3c2440-i2c.3", "i2c3", "aclk100",
GATE_IP_PERIL, 9, 0, 0, "i2c"),
GATE_DA(i2c4, "s3c2440-i2c.4", "i2c4", "aclk100",
GATE_IP_PERIL, 10, 0, 0, "i2c"),
GATE_DA(i2c5, "s3c2440-i2c.5", "i2c5", "aclk100",
GATE_IP_PERIL, 11, 0, 0, "i2c"),
GATE_DA(i2c6, "s3c2440-i2c.6", "i2c6", "aclk100",
GATE_IP_PERIL, 12, 0, 0, "i2c"),
GATE_DA(i2c7, "s3c2440-i2c.7", "i2c7", "aclk100",
GATE_IP_PERIL, 13, 0, 0, "i2c"),
GATE_DA(i2c_hdmi, "s3c2440-hdmiphy-i2c", "i2c-hdmi", "aclk100",
GATE_IP_PERIL, 14, 0, 0, "i2c"),
GATE_DA(spi0, "exynos4210-spi.0", "spi0", "aclk100",
GATE_IP_PERIL, 16, 0, 0, "spi"),
GATE_DA(spi1, "exynos4210-spi.1", "spi1", "aclk100",
GATE_IP_PERIL, 17, 0, 0, "spi"),
GATE_DA(spi2, "exynos4210-spi.2", "spi2", "aclk100",
GATE_IP_PERIL, 18, 0, 0, "spi"),
GATE_DA(i2s1, "samsung-i2s.1", "i2s1", "aclk100",
GATE_IP_PERIL, 20, 0, 0, "iis"),
GATE_DA(i2s2, "samsung-i2s.2", "i2s2", "aclk100",
GATE_IP_PERIL, 21, 0, 0, "iis"),
GATE_DA(pcm1, "samsung-pcm.1", "pcm1", "aclk100",
GATE_IP_PERIL, 22, 0, 0, "pcm"),
GATE_DA(pcm2, "samsung-pcm.2", "pcm2", "aclk100",
GATE_IP_PERIL, 23, 0, 0, "pcm"),
GATE_DA(spdif, "samsung-spdif", "spdif", "aclk100",
GATE_IP_PERIL, 26, 0, 0, "spdif"),
GATE_DA(ac97, "samsung-ac97", "ac97", "aclk100",
GATE_IP_PERIL, 27, 0, 0, "ac97"),
GATE(smmu_tv, "smmu_tv", "aclk160", GATE_IP_TV, 4,
0, 0),
GATE(mfc, "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0),
GATE(smmu_mfcl, "smmu_mfcl", "aclk100", GATE_IP_MFC, 1,
0, 0),
GATE(smmu_mfcr, "smmu_mfcr", "aclk100", GATE_IP_MFC, 2,
0, 0),
GATE(fimd0, "fimd0", "aclk160", GATE_IP_LCD0, 0,
0, 0),
GATE(smmu_fimd0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4,
0, 0),
GATE(pdma0, "pdma0", "aclk133", GATE_IP_FSYS, 0,
0, 0),
GATE(pdma1, "pdma1", "aclk133", GATE_IP_FSYS, 1,
0, 0),
GATE(sdmmc0, "sdmmc0", "aclk133", GATE_IP_FSYS, 5,
0, 0),
GATE(sdmmc1, "sdmmc1", "aclk133", GATE_IP_FSYS, 6,
0, 0),
GATE(sdmmc2, "sdmmc2", "aclk133", GATE_IP_FSYS, 7,
0, 0),
GATE(sdmmc3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8,
0, 0),
GATE(uart0, "uart0", "aclk100", GATE_IP_PERIL, 0,
0, 0),
GATE(uart1, "uart1", "aclk100", GATE_IP_PERIL, 1,
0, 0),
GATE(uart2, "uart2", "aclk100", GATE_IP_PERIL, 2,
0, 0),
GATE(uart3, "uart3", "aclk100", GATE_IP_PERIL, 3,
0, 0),
GATE(uart4, "uart4", "aclk100", GATE_IP_PERIL, 4,
0, 0),
GATE(i2c0, "i2c0", "aclk100", GATE_IP_PERIL, 6,
0, 0),
GATE(i2c1, "i2c1", "aclk100", GATE_IP_PERIL, 7,
0, 0),
GATE(i2c2, "i2c2", "aclk100", GATE_IP_PERIL, 8,
0, 0),
GATE(i2c3, "i2c3", "aclk100", GATE_IP_PERIL, 9,
0, 0),
GATE(i2c4, "i2c4", "aclk100", GATE_IP_PERIL, 10,
0, 0),
GATE(i2c5, "i2c5", "aclk100", GATE_IP_PERIL, 11,
0, 0),
GATE(i2c6, "i2c6", "aclk100", GATE_IP_PERIL, 12,
0, 0),
GATE(i2c7, "i2c7", "aclk100", GATE_IP_PERIL, 13,
0, 0),
GATE(i2c_hdmi, "i2c-hdmi", "aclk100", GATE_IP_PERIL, 14,
0, 0),
GATE(spi0, "spi0", "aclk100", GATE_IP_PERIL, 16,
0, 0),
GATE(spi1, "spi1", "aclk100", GATE_IP_PERIL, 17,
0, 0),
GATE(spi2, "spi2", "aclk100", GATE_IP_PERIL, 18,
0, 0),
GATE(i2s1, "i2s1", "aclk100", GATE_IP_PERIL, 20,
0, 0),
GATE(i2s2, "i2s2", "aclk100", GATE_IP_PERIL, 21,
0, 0),
GATE(pcm1, "pcm1", "aclk100", GATE_IP_PERIL, 22,
0, 0),
GATE(pcm2, "pcm2", "aclk100", GATE_IP_PERIL, 23,
0, 0),
GATE(spdif, "spdif", "aclk100", GATE_IP_PERIL, 26,
0, 0),
GATE(ac97, "ac97", "aclk100", GATE_IP_PERIL, 27,
0, 0),
};
/* list of gate clocks supported in exynos4210 soc */
struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
GATE(tvenc, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
GATE(g2d, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
GATE(rotator, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
@ -811,17 +803,23 @@ struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
GATE(sclk_mixer, "sclk_mixer", "mout_mixer", SRC_MASK_TV, 4, 0, 0),
GATE(sclk_dac, "sclk_dac", "mout_dac", SRC_MASK_TV, 8, 0, 0),
GATE_A(tsadc, "tsadc", "aclk100", GATE_IP_PERIL, 15, 0, 0, "adc"),
GATE_A(mct, "mct", "aclk100", E4210_GATE_IP_PERIR, 13, 0, 0, "mct"),
GATE_A(wdt, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14, 0, 0, "watchdog"),
GATE_A(rtc, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15, 0, 0, "rtc"),
GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"),
GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1",
E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
GATE(tsadc, "tsadc", "aclk100", GATE_IP_PERIL, 15,
0, 0),
GATE(mct, "mct", "aclk100", E4210_GATE_IP_PERIR, 13,
0, 0),
GATE(wdt, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14,
0, 0),
GATE(rtc, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15,
0, 0),
GATE(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16,
0, 0),
GATE(sclk_fimd1, "sclk_fimd1", "div_fimd1", E4210_SRC_MASK_LCD1, 0,
CLK_SET_RATE_PARENT, 0),
GATE(tmu_apbif, "tmu_apbif", "aclk100", E4210_GATE_IP_PERIR, 17, 0, 0),
};
/* list of gate clocks supported in exynos4x12 soc */
struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
GATE(audss, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
GATE(mdnie0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
GATE(rotator, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
@ -840,10 +838,11 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
GATE(smmu_rotator, "smmu_rotator", "aclk200",
E4X12_GATE_IP_IMAGE, 4, 0, 0),
GATE_A(mct, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13, 0, 0, "mct"),
GATE_A(rtc, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15, 0, 0, "rtc"),
GATE_A(keyif, "keyif", "aclk100",
E4X12_GATE_IP_PERIR, 16, 0, 0, "keypad"),
GATE(mct, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13,
0, 0),
GATE(rtc, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15,
0, 0),
GATE(keyif, "keyif", "aclk100", E4X12_GATE_IP_PERIR, 16, 0, 0),
GATE(sclk_pwm_isp, "sclk_pwm_isp", "div_pwm_isp",
E4X12_SRC_MASK_ISP, 0, CLK_SET_RATE_PARENT, 0),
GATE(sclk_spi0_isp, "sclk_spi0_isp", "div_spi0_isp_pre",
@ -860,12 +859,11 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
E4X12_GATE_IP_ISP, 2, 0, 0),
GATE(uart_isp_sclk, "uart_isp_sclk", "sclk_uart_isp",
E4X12_GATE_IP_ISP, 3, 0, 0),
GATE_A(wdt, "watchdog", "aclk100",
E4X12_GATE_IP_PERIR, 14, 0, 0, "watchdog"),
GATE_DA(pcm0, "samsung-pcm.0", "pcm0", "aclk100",
E4X12_GATE_IP_MAUDIO, 2, 0, 0, "pcm"),
GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100",
E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"),
GATE(wdt, "watchdog", "aclk100", E4X12_GATE_IP_PERIR, 14, 0, 0),
GATE(pcm0, "pcm0", "aclk100", E4X12_GATE_IP_MAUDIO, 2,
0, 0),
GATE(i2s0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3,
0, 0),
GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0,
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1,
@ -919,6 +917,21 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
GATE(tmu_apbif, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0, 0),
};
static struct samsung_clock_alias exynos4_aliases[] __initdata = {
ALIAS(mout_core, NULL, "moutcore"),
ALIAS(arm_clk, NULL, "armclk"),
ALIAS(sclk_apll, NULL, "mout_apll"),
};
static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
ALIAS(sclk_mpll, NULL, "mout_mpll"),
};
static struct samsung_clock_alias exynos4x12_aliases[] __initdata = {
ALIAS(mout_mpll_user_c, NULL, "mout_mpll"),
};
/*
@ -973,36 +986,116 @@ static void __init exynos4_clk_register_finpll(unsigned long xom)
}
/*
* This function allows non-dt platforms to specify the clock speed of the
* xxti and xusbxti clocks. These clocks are then registered with the specified
* clock speed.
*/
void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
unsigned long xusbxti_f)
{
exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
}
static __initdata struct of_device_id ext_clk_match[] = {
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
{ .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
{},
};
/* register exynos4 clocks */
void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
{
struct clk *apll, *mpll, *epll, *vpll;
/* PLLs PMS values */
static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = {
PLL_45XX_RATE(1200000000, 150, 3, 1, 28),
PLL_45XX_RATE(1000000000, 250, 6, 1, 28),
PLL_45XX_RATE( 800000000, 200, 6, 1, 28),
PLL_45XX_RATE( 666857142, 389, 14, 1, 13),
PLL_45XX_RATE( 600000000, 100, 4, 1, 13),
PLL_45XX_RATE( 533000000, 533, 24, 1, 5),
PLL_45XX_RATE( 500000000, 250, 6, 2, 28),
PLL_45XX_RATE( 400000000, 200, 6, 2, 28),
PLL_45XX_RATE( 200000000, 200, 6, 3, 28),
{ /* sentinel */ }
};
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
}
static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = {
PLL_4600_RATE(192000000, 48, 3, 1, 0, 0),
PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0),
PLL_4600_RATE(180000000, 45, 3, 1, 0, 0),
PLL_4600_RATE( 73727996, 73, 3, 3, 47710, 1),
PLL_4600_RATE( 67737602, 90, 4, 3, 20762, 1),
PLL_4600_RATE( 49151992, 49, 3, 3, 9961, 0),
PLL_4600_RATE( 45158401, 45, 3, 3, 10381, 0),
{ /* sentinel */ }
};
static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = {
PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0),
PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1, 1, 1),
PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1),
PLL_4650_RATE(110000000, 53, 3, 2, 2048, 0, 17, 0),
PLL_4650_RATE( 55360351, 53, 3, 3, 2417, 0, 17, 0),
{ /* sentinel */ }
};
static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = {
PLL_35XX_RATE(1500000000, 250, 4, 0),
PLL_35XX_RATE(1400000000, 175, 3, 0),
PLL_35XX_RATE(1300000000, 325, 6, 0),
PLL_35XX_RATE(1200000000, 200, 4, 0),
PLL_35XX_RATE(1100000000, 275, 6, 0),
PLL_35XX_RATE(1000000000, 125, 3, 0),
PLL_35XX_RATE( 900000000, 150, 4, 0),
PLL_35XX_RATE( 800000000, 100, 3, 0),
PLL_35XX_RATE( 700000000, 175, 3, 1),
PLL_35XX_RATE( 600000000, 200, 4, 1),
PLL_35XX_RATE( 500000000, 125, 3, 1),
PLL_35XX_RATE( 400000000, 100, 3, 1),
PLL_35XX_RATE( 300000000, 200, 4, 2),
PLL_35XX_RATE( 200000000, 100, 3, 2),
{ /* sentinel */ }
};
static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = {
PLL_36XX_RATE(192000000, 48, 3, 1, 0),
PLL_36XX_RATE(180633605, 45, 3, 1, 10381),
PLL_36XX_RATE(180000000, 45, 3, 1, 0),
PLL_36XX_RATE( 73727996, 73, 3, 3, 47710),
PLL_36XX_RATE( 67737602, 90, 4, 3, 20762),
PLL_36XX_RATE( 49151992, 49, 3, 3, 9961),
PLL_36XX_RATE( 45158401, 45, 3, 3, 10381),
{ /* sentinel */ }
};
static struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initdata = {
PLL_36XX_RATE(533000000, 133, 3, 1, 16384),
PLL_36XX_RATE(440000000, 110, 3, 1, 0),
PLL_36XX_RATE(350000000, 175, 3, 2, 0),
PLL_36XX_RATE(266000000, 133, 3, 2, 0),
PLL_36XX_RATE(160000000, 160, 3, 3, 0),
PLL_36XX_RATE(106031250, 53, 3, 2, 1024),
PLL_36XX_RATE( 53015625, 53, 3, 3, 1024),
{ /* sentinel */ }
};
static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = {
[apll] = PLL_A(pll_4508, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
APLL_CON0, "fout_apll", NULL),
[mpll] = PLL_A(pll_4508, fout_mpll, "fout_mpll", "fin_pll",
E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL),
[epll] = PLL_A(pll_4600, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
EPLL_CON0, "fout_epll", NULL),
[vpll] = PLL_A(pll_4650c, fout_vpll, "fout_vpll", "mout_vpllsrc",
VPLL_LOCK, VPLL_CON0, "fout_vpll", NULL),
};
static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
[apll] = PLL(pll_35xx, fout_apll, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON0, NULL),
[mpll] = PLL(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
E4X12_MPLL_LOCK, E4X12_MPLL_CON0, NULL),
[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll",
EPLL_LOCK, EPLL_CON0, NULL),
[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll",
VPLL_LOCK, VPLL_CON0, NULL),
};
/* register exynos4 clocks */
static void __init exynos4_clk_init(struct device_node *np,
enum exynos4_soc exynos4_soc,
void __iomem *reg_base, unsigned long xom)
{
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
if (exynos4_soc == EXYNOS4210)
samsung_clk_init(np, reg_base, nr_clks,
@ -1013,37 +1106,42 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save));
if (np)
samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
ext_clk_match);
exynos4_clk_register_finpll(xom);
if (exynos4_soc == EXYNOS4210) {
apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll",
reg_base + APLL_CON0, pll_4508);
mpll = samsung_clk_register_pll45xx("fout_mpll", "fin_pll",
reg_base + E4210_MPLL_CON0, pll_4508);
epll = samsung_clk_register_pll46xx("fout_epll", "fin_pll",
reg_base + EPLL_CON0, pll_4600);
vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
reg_base + VPLL_CON0, pll_4650c);
} else {
apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
reg_base + APLL_CON0);
mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
reg_base + E4X12_MPLL_CON0);
epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
reg_base + EPLL_CON0);
vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
reg_base + VPLL_CON0);
}
samsung_clk_register_mux(exynos4210_mux_early,
ARRAY_SIZE(exynos4210_mux_early));
samsung_clk_add_lookup(apll, fout_apll);
samsung_clk_add_lookup(mpll, fout_mpll);
samsung_clk_add_lookup(epll, fout_epll);
samsung_clk_add_lookup(vpll, fout_vpll);
if (_get_rate("fin_pll") == 24000000) {
exynos4210_plls[apll].rate_table =
exynos4210_apll_rates;
exynos4210_plls[epll].rate_table =
exynos4210_epll_rates;
}
if (_get_rate("mout_vpllsrc") == 24000000)
exynos4210_plls[vpll].rate_table =
exynos4210_vpll_rates;
samsung_clk_register_pll(exynos4210_plls,
ARRAY_SIZE(exynos4210_plls), reg_base);
} else {
if (_get_rate("fin_pll") == 24000000) {
exynos4x12_plls[apll].rate_table =
exynos4x12_apll_rates;
exynos4x12_plls[epll].rate_table =
exynos4x12_epll_rates;
exynos4x12_plls[vpll].rate_table =
exynos4x12_vpll_rates;
}
samsung_clk_register_pll(exynos4x12_plls,
ARRAY_SIZE(exynos4x12_plls), reg_base);
}
samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
@ -1063,6 +1161,8 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
ARRAY_SIZE(exynos4210_div_clks));
samsung_clk_register_gate(exynos4210_gate_clks,
ARRAY_SIZE(exynos4210_gate_clks));
samsung_clk_register_alias(exynos4210_aliases,
ARRAY_SIZE(exynos4210_aliases));
} else {
samsung_clk_register_mux(exynos4x12_mux_clks,
ARRAY_SIZE(exynos4x12_mux_clks));
@ -1070,14 +1170,19 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
ARRAY_SIZE(exynos4x12_div_clks));
samsung_clk_register_gate(exynos4x12_gate_clks,
ARRAY_SIZE(exynos4x12_gate_clks));
samsung_clk_register_alias(exynos4x12_aliases,
ARRAY_SIZE(exynos4x12_aliases));
}
samsung_clk_register_alias(exynos4_aliases,
ARRAY_SIZE(exynos4_aliases));
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
_get_rate("sclk_apll"), _get_rate("mout_mpll"),
_get_rate("sclk_apll"), _get_rate("sclk_mpll"),
_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
_get_rate("armclk"));
_get_rate("arm_clk"));
}

View File

@ -17,11 +17,22 @@
#include <linux/of_address.h>
#include "clk.h"
#include "clk-pll.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
#define SRC_CPU 0x200
#define DIV_CPU0 0x500
#define MPLL_LOCK 0x4000
#define MPLL_CON0 0x4100
#define SRC_CORE1 0x4204
#define CPLL_LOCK 0x10020
#define EPLL_LOCK 0x10030
#define VPLL_LOCK 0x10040
#define GPLL_LOCK 0x10050
#define CPLL_CON0 0x10120
#define EPLL_CON0 0x10130
#define VPLL_CON0 0x10140
#define GPLL_CON0 0x10150
#define SRC_TOP0 0x10210
#define SRC_TOP2 0x10218
#define SRC_GSCL 0x10220
@ -59,9 +70,18 @@
#define GATE_IP_FSYS 0x10944
#define GATE_IP_PERIC 0x10950
#define GATE_IP_PERIS 0x10960
#define BPLL_LOCK 0x20010
#define BPLL_CON0 0x20110
#define SRC_CDREX 0x20200
#define PLL_DIV2_SEL 0x20a24
#define GATE_IP_DISP1 0x10928
#define GATE_IP_ACP 0x10000
/* list of PLLs to be registered */
enum exynos5250_plls {
apll, mpll, cpll, epll, vpll, gpll, bpll,
nr_plls /* number of PLLs */
};
/*
* Let each supported clock get a unique id. This id is used to lookup the clock
@ -79,7 +99,8 @@ enum exynos5250_clks {
none,
/* core clocks */
fin_pll,
fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll,
fout_epll, fout_vpll,
/* gate for special clocks (sclk) */
sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
@ -87,7 +108,7 @@ enum exynos5250_clks {
sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
div_i2s1, div_i2s2,
div_i2s1, div_i2s2, sclk_hdmiphy,
/* gate clocks */
gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
@ -99,7 +120,10 @@ enum exynos5250_clks {
spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
/* mux clocks */
mout_hdmi = 1024,
nr_clks,
};
@ -108,7 +132,7 @@ enum exynos5250_clks {
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static __initdata unsigned long exynos5250_clk_regs[] = {
static unsigned long exynos5250_clk_regs[] __initdata = {
SRC_CPU,
DIV_CPU0,
SRC_CORE1,
@ -152,6 +176,7 @@ static __initdata unsigned long exynos5250_clk_regs[] = {
SRC_CDREX,
PLL_DIV2_SEL,
GATE_IP_DISP1,
GATE_IP_ACP,
};
/* list of all parent clock list */
@ -191,31 +216,34 @@ PNAME(mout_spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
"spdif_extclk" };
/* fixed rate clocks generated outside the soc */
struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
};
/* fixed rate clocks generated inside the soc */
struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
};
struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
};
struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
};
static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX_A(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, "mout_apll"),
MUX_A(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
MUX_A(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"),
MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
@ -232,7 +260,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
MUX(mout_hdmi, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
@ -254,7 +282,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
};
struct samsung_div_clock exynos5250_div_clks[] __initdata = {
static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3),
@ -314,7 +342,7 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = {
DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
};
struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0),
GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0),
GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0),
@ -461,20 +489,60 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
GATE(mie1, "mie1", "aclk200", GATE_IP_DISP1, 1, 0, 0),
GATE(dsim0, "dsim0", "aclk200", GATE_IP_DISP1, 3, 0, 0),
GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
};
static __initdata struct of_device_id ext_clk_match[] = {
static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(266000000, 266, 3, 3, 0),
/* Not in UM, but need for eDP on snow */
PLL_36XX_RATE(70500000, 94, 2, 4, 0),
{ },
};
static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(192000000, 64, 2, 2, 0),
PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
{ },
};
static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
APLL_CON0, "fout_apll", NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
MPLL_CON0, "fout_mpll", NULL),
[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
BPLL_CON0, NULL),
[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
GPLL_CON0, NULL),
[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
CPLL_CON0, NULL),
[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
EPLL_CON0, NULL),
[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc",
VPLL_LOCK, VPLL_CON0, NULL),
};
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
{ },
};
/* register exynox5250 clocks */
void __init exynos5250_clk_init(struct device_node *np)
static void __init exynos5250_clk_init(struct device_node *np)
{
void __iomem *reg_base;
struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
if (np) {
reg_base = of_iomap(np, 0);
@ -490,22 +558,17 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
reg_base + 0x100);
mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
reg_base + 0x4100);
bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
reg_base + 0x20110);
gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
reg_base + 0x10150);
cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
reg_base + 0x10120);
epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
reg_base + 0x10130);
vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
reg_base + 0x10140);
if (_get_rate("fin_pll") == 24 * MHZ)
exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
if (_get_rate("mout_vpllsrc") == 24 * MHZ)
exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,

View File

@ -17,13 +17,30 @@
#include <linux/of_address.h>
#include "clk.h"
#include "clk-pll.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
#define SRC_CPU 0x200
#define DIV_CPU0 0x500
#define DIV_CPU1 0x504
#define GATE_BUS_CPU 0x700
#define GATE_SCLK_CPU 0x800
#define CPLL_LOCK 0x10020
#define DPLL_LOCK 0x10030
#define EPLL_LOCK 0x10040
#define RPLL_LOCK 0x10050
#define IPLL_LOCK 0x10060
#define SPLL_LOCK 0x10070
#define VPLL_LOCK 0x10070
#define MPLL_LOCK 0x10090
#define CPLL_CON0 0x10120
#define DPLL_CON0 0x10128
#define EPLL_CON0 0x10130
#define RPLL_CON0 0x10140
#define IPLL_CON0 0x10150
#define SPLL_CON0 0x10160
#define VPLL_CON0 0x10170
#define MPLL_CON0 0x10180
#define SRC_TOP0 0x10200
#define SRC_TOP1 0x10204
#define SRC_TOP2 0x10208
@ -75,15 +92,27 @@
#define GATE_TOP_SCLK_MAU 0x1083c
#define GATE_TOP_SCLK_FSYS 0x10840
#define GATE_TOP_SCLK_PERIC 0x10850
#define BPLL_LOCK 0x20010
#define BPLL_CON0 0x20110
#define SRC_CDREX 0x20200
#define KPLL_LOCK 0x28000
#define KPLL_CON0 0x28100
#define SRC_KFC 0x28200
#define DIV_KFC0 0x28500
/* list of PLLs */
enum exynos5420_plls {
apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll,
bpll, kpll,
nr_plls /* number of PLLs */
};
enum exynos5420_clks {
none,
/* core clocks */
fin_pll,
fin_pll, fout_apll, fout_cpll, fout_dpll, fout_epll, fout_rpll,
fout_ipll, fout_spll, fout_vpll, fout_mpll, fout_bpll, fout_kpll,
/* gate for special clocks (sclk) */
sclk_uart0 = 128, sclk_uart1, sclk_uart2, sclk_uart3, sclk_mmc0,
@ -91,7 +120,7 @@ enum exynos5420_clks {
sclk_i2s2, sclk_pcm1, sclk_pcm2, sclk_spdif, sclk_hdmi, sclk_pixel,
sclk_dp1, sclk_mipi1, sclk_fimd1, sclk_maudio0, sclk_maupcm0,
sclk_usbd300, sclk_usbd301, sclk_usbphy300, sclk_usbphy301, sclk_unipro,
sclk_pwm, sclk_gscl_wa, sclk_gscl_wb,
sclk_pwm, sclk_gscl_wa, sclk_gscl_wb, sclk_hdmiphy,
/* gate clocks */
aclk66_peric = 256, uart0, uart1, uart2, uart3, i2c0, i2c1, i2c2, i2c3,
@ -109,7 +138,13 @@ enum exynos5420_clks {
aclk300_gscl = 460, smmu_gscl0, smmu_gscl1, gscl_wa, gscl_wb, gscl0,
gscl1, clk_3aa, aclk266_g2d = 470, sss, slim_sss, mdma0,
aclk333_g2d = 480, g2d, aclk333_432_gscl = 490, smmu_3aa, smmu_fimcl0,
smmu_fimcl1, smmu_fimcl3, fimc_lite3, aclk_g3d = 500, g3d,
smmu_fimcl1, smmu_fimcl3, fimc_lite3, aclk_g3d = 500, g3d, smmu_mixer,
/* mux clocks */
mout_hdmi = 640,
/* divider clocks */
dout_pixel = 768,
nr_clks,
};
@ -118,7 +153,7 @@ enum exynos5420_clks {
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
*/
static __initdata unsigned long exynos5420_clk_regs[] = {
static unsigned long exynos5420_clk_regs[] __initdata = {
SRC_CPU,
DIV_CPU0,
DIV_CPU1,
@ -257,29 +292,29 @@ PNAME(audio2_p) = { "fin_pll", "cdclk2", "sclk_dpll", "sclk_mpll",
"sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" };
PNAME(spdif_p) = { "fin_pll", "dout_audio0", "dout_audio1", "dout_audio2",
"spdif_extclk", "sclk_ipll", "sclk_epll", "sclk_rpll" };
PNAME(hdmi_p) = { "sclk_hdmiphy", "dout_hdmi_pixel" };
PNAME(hdmi_p) = { "dout_hdmi_pixel", "sclk_hdmiphy" };
PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll",
"sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" };
/* fixed rate clocks generated outside the soc */
struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = {
FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
};
/* fixed rate clocks generated inside the soc */
struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = {
FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000),
FRATE(none, "mphy_refclk_ixtal24", NULL, CLK_IS_ROOT, 48000000),
FRATE(none, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000),
};
struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = {
static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = {
FFACTOR(none, "sclk_hsic_12m", "fin_pll", 1, 2, 0),
};
struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
MUX(none, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2),
MUX(none, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2),
MUX(none, "mout_apll", apll_p, SRC_CPU, 0, 1),
@ -371,7 +406,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
MUX(none, "mout_mipi1", group2_p, SRC_DISP10, 16, 3),
MUX(none, "mout_dp1", group2_p, SRC_DISP10, 20, 3),
MUX(none, "mout_pixel", group2_p, SRC_DISP10, 24, 3),
MUX(none, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1),
MUX(mout_hdmi, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1),
/* MAU Block */
MUX(none, "mout_maudio0", maudio0_p, SRC_MAU, 28, 3),
@ -399,7 +434,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
MUX(none, "mout_spi2", group2_p, SRC_PERIC1, 28, 3),
};
struct samsung_div_clock exynos5420_div_clks[] __initdata = {
static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
DIV(none, "armclk2", "div_arm", DIV_CPU0, 28, 3),
@ -431,7 +466,7 @@ struct samsung_div_clock exynos5420_div_clks[] __initdata = {
DIV(none, "dout_fimd1", "mout_fimd1", DIV_DISP10, 0, 4),
DIV(none, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8),
DIV(none, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4),
DIV(none, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
DIV(dout_pixel, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
/* Audio Block */
DIV(none, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4),
@ -479,7 +514,7 @@ struct samsung_div_clock exynos5420_div_clks[] __initdata = {
DIV(none, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8),
};
struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
/* TODO: Re-verify the CG bits for all the gate clocks */
GATE_A(mct, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, "mct"),
@ -696,19 +731,43 @@ struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
GATE(smmu_mscl0, "smmu_mscl0", "aclk400_mscl", GATE_IP_MSCL, 8, 0, 0),
GATE(smmu_mscl1, "smmu_mscl1", "aclk400_mscl", GATE_IP_MSCL, 9, 0, 0),
GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, 0),
GATE(smmu_mixer, "smmu_mixer", "aclk200_disp1", GATE_IP_DISP1, 9, 0, 0),
};
static __initdata struct of_device_id ext_clk_match[] = {
static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = {
[apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
APLL_CON0, NULL),
[cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
MPLL_CON0, NULL),
[dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK,
DPLL_CON0, NULL),
[epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
EPLL_CON0, NULL),
[rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", RPLL_LOCK,
RPLL_CON0, NULL),
[ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", IPLL_LOCK,
IPLL_CON0, NULL),
[spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", SPLL_LOCK,
SPLL_CON0, NULL),
[vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
VPLL_CON0, NULL),
[mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
MPLL_CON0, NULL),
[bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
BPLL_CON0, NULL),
[kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", KPLL_LOCK,
KPLL_CON0, NULL),
};
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
{ },
};
/* register exynos5420 clocks */
void __init exynos5420_clk_init(struct device_node *np)
static void __init exynos5420_clk_init(struct device_node *np)
{
void __iomem *reg_base;
struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll;
struct clk *rpll, *spll, *vpll;
if (np) {
reg_base = of_iomap(np, 0);
@ -724,30 +783,8 @@ void __init exynos5420_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
ext_clk_match);
apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
reg_base + 0x100);
bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
reg_base + 0x20110);
cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
reg_base + 0x10120);
dpll = samsung_clk_register_pll35xx("fout_dpll", "fin_pll",
reg_base + 0x10128);
epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
reg_base + 0x10130);
ipll = samsung_clk_register_pll35xx("fout_ipll", "fin_pll",
reg_base + 0x10150);
kpll = samsung_clk_register_pll35xx("fout_kpll", "fin_pll",
reg_base + 0x28100);
mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
reg_base + 0x10180);
rpll = samsung_clk_register_pll36xx("fout_rpll", "fin_pll",
reg_base + 0x10140);
spll = samsung_clk_register_pll35xx("fout_spll", "fin_pll",
reg_base + 0x10160);
vpll = samsung_clk_register_pll35xx("fout_vpll", "fin_pll",
reg_base + 0x10170);
samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
ARRAY_SIZE(exynos5420_fixed_rate_clks));
samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,

View File

@ -41,12 +41,12 @@ PNAME(mout_armclk_p) = { "cplla", "cpllb" };
PNAME(mout_spi_p) = { "div125", "div200" };
/* fixed rate clocks generated outside the soc */
struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0),
};
/* fixed rate clocks */
struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000),
FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
@ -55,26 +55,26 @@ struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
};
/* fixed factor clocks */
struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
FFACTOR(none, "div250", "ppll", 1, 4, 0),
FFACTOR(none, "div200", "ppll", 1, 5, 0),
FFACTOR(none, "div125", "div250", 1, 2, 0),
};
/* mux clocks */
struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
MUX_A(arm_clk, "arm_clk", mout_armclk_p,
CPU_CLK_STATUS, 0, 1, "armclk"),
};
/* divider clocks */
struct samsung_div_clock exynos5440_div_clks[] __initdata = {
static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
};
/* gate clocks */
struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
@ -97,13 +97,13 @@ struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
GATE(cs250_o, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
};
static __initdata struct of_device_id ext_clk_match[] = {
static struct of_device_id ext_clk_match[] __initdata = {
{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
{},
};
/* register exynos5440 clocks */
void __init exynos5440_clk_init(struct device_node *np)
static void __init exynos5440_clk_init(struct device_node *np)
{
void __iomem *reg_base;
@ -132,7 +132,7 @@ void __init exynos5440_clk_init(struct device_node *np)
samsung_clk_register_gate(exynos5440_gate_clks,
ARRAY_SIZE(exynos5440_gate_clks));
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("armclk"));
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
pr_info("exynos5440 clock initialization complete\n");
}
CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);

View File

@ -10,31 +10,73 @@
*/
#include <linux/errno.h>
#include <linux/hrtimer.h>
#include "clk.h"
#include "clk-pll.h"
#define PLL_TIMEOUT_MS 10
struct samsung_clk_pll {
struct clk_hw hw;
void __iomem *lock_reg;
void __iomem *con_reg;
enum samsung_pll_type type;
unsigned int rate_count;
const struct samsung_pll_rate_table *rate_table;
};
#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
static const struct samsung_pll_rate_table *samsung_get_pll_settings(
struct samsung_clk_pll *pll, unsigned long rate)
{
const struct samsung_pll_rate_table *rate_table = pll->rate_table;
int i;
for (i = 0; i < pll->rate_count; i++) {
if (rate == rate_table[i].rate)
return &rate_table[i];
}
return NULL;
}
static long samsung_pll_round_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_table = pll->rate_table;
int i;
/* Assumming rate_table is in descending order */
for (i = 0; i < pll->rate_count; i++) {
if (drate >= rate_table[i].rate)
return rate_table[i].rate;
}
/* return minimum supported value */
return rate_table[i - 1].rate;
}
/*
* PLL35xx Clock Type
*/
/* Maximum lock time can be 270 * PDIV cycles */
#define PLL35XX_LOCK_FACTOR (270)
#define PLL35XX_MDIV_MASK (0x3FF)
#define PLL35XX_PDIV_MASK (0x3F)
#define PLL35XX_SDIV_MASK (0x7)
#define PLL35XX_LOCK_STAT_MASK (0x1)
#define PLL35XX_MDIV_SHIFT (16)
#define PLL35XX_PDIV_SHIFT (8)
#define PLL35XX_SDIV_SHIFT (0)
struct samsung_clk_pll35xx {
struct clk_hw hw;
const void __iomem *con_reg;
};
#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
#define PLL35XX_LOCK_STAT_SHIFT (29)
static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
@ -49,48 +91,80 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
return (unsigned long)fvco;
}
static inline bool samsung_pll35xx_mp_change(
const struct samsung_pll_rate_table *rate, u32 pll_con)
{
u32 old_mdiv, old_pdiv;
old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
}
static int samsung_pll35xx_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);
if (!(samsung_pll35xx_mp_change(rate, tmp))) {
/* If only s change, change just s value only*/
tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
__raw_writel(tmp, pll->con_reg);
return 0;
}
/* Set PLL lock time. */
__raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
pll->lock_reg);
/* Change PLL PMS values */
tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
(PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
(rate->pdiv << PLL35XX_PDIV_SHIFT) |
(rate->sdiv << PLL35XX_SDIV_SHIFT);
__raw_writel(tmp, pll->con_reg);
/* wait_lock_time */
do {
cpu_relax();
tmp = __raw_readl(pll->con_reg);
} while (!(tmp & (PLL35XX_LOCK_STAT_MASK
<< PLL35XX_LOCK_STAT_SHIFT)));
return 0;
}
static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
.round_rate = samsung_pll_round_rate,
.set_rate = samsung_pll35xx_set_rate,
};
struct clk * __init samsung_clk_register_pll35xx(const char *name,
const char *pname, const void __iomem *con_reg)
{
struct samsung_clk_pll35xx *pll;
struct clk *clk;
struct clk_init_data init;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll) {
pr_err("%s: could not allocate pll clk %s\n", __func__, name);
return NULL;
}
init.name = name;
init.ops = &samsung_pll35xx_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE;
init.parent_names = &pname;
init.num_parents = 1;
pll->hw.init = &init;
pll->con_reg = con_reg;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s\n", __func__,
name);
kfree(pll);
}
if (clk_register_clkdev(clk, name, NULL))
pr_err("%s: failed to register lookup for %s", __func__, name);
return clk;
}
static const struct clk_ops samsung_pll35xx_clk_min_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
};
/*
* PLL36xx Clock Type
*/
/* Maximum lock time can be 3000 * PDIV cycles */
#define PLL36XX_LOCK_FACTOR (3000)
#define PLL36XX_KDIV_MASK (0xFFFF)
#define PLL36XX_MDIV_MASK (0x1FF)
@ -99,18 +173,13 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name,
#define PLL36XX_MDIV_SHIFT (16)
#define PLL36XX_PDIV_SHIFT (8)
#define PLL36XX_SDIV_SHIFT (0)
struct samsung_clk_pll36xx {
struct clk_hw hw;
const void __iomem *con_reg;
};
#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
#define PLL36XX_KDIV_SHIFT (0)
#define PLL36XX_LOCK_STAT_SHIFT (29)
static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
s16 kdiv;
u64 fvco = parent_rate;
@ -129,68 +198,102 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
return (unsigned long)fvco;
}
static inline bool samsung_pll36xx_mpk_change(
const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
{
u32 old_mdiv, old_pdiv, old_kdiv;
old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
rate->kdiv != old_kdiv);
}
static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long parent_rate)
{
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 tmp, pll_con0, pll_con1;
const struct samsung_pll_rate_table *rate;
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;
}
pll_con0 = __raw_readl(pll->con_reg);
pll_con1 = __raw_readl(pll->con_reg + 4);
if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
/* If only s change, change just s value only*/
pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
__raw_writel(pll_con0, pll->con_reg);
return 0;
}
/* Set PLL lock time. */
__raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
/* Change PLL PMS values */
pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
(PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
(rate->pdiv << PLL36XX_PDIV_SHIFT) |
(rate->sdiv << PLL36XX_SDIV_SHIFT);
__raw_writel(pll_con0, pll->con_reg);
pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
__raw_writel(pll_con1, pll->con_reg + 4);
/* wait_lock_time */
do {
cpu_relax();
tmp = __raw_readl(pll->con_reg);
} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
return 0;
}
static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
.set_rate = samsung_pll36xx_set_rate,
.round_rate = samsung_pll_round_rate,
};
struct clk * __init samsung_clk_register_pll36xx(const char *name,
const char *pname, const void __iomem *con_reg)
{
struct samsung_clk_pll36xx *pll;
struct clk *clk;
struct clk_init_data init;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll) {
pr_err("%s: could not allocate pll clk %s\n", __func__, name);
return NULL;
}
init.name = name;
init.ops = &samsung_pll36xx_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE;
init.parent_names = &pname;
init.num_parents = 1;
pll->hw.init = &init;
pll->con_reg = con_reg;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s\n", __func__,
name);
kfree(pll);
}
if (clk_register_clkdev(clk, name, NULL))
pr_err("%s: failed to register lookup for %s", __func__, name);
return clk;
}
static const struct clk_ops samsung_pll36xx_clk_min_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
};
/*
* PLL45xx Clock Type
*/
#define PLL4502_LOCK_FACTOR 400
#define PLL4508_LOCK_FACTOR 240
#define PLL45XX_MDIV_MASK (0x3FF)
#define PLL45XX_PDIV_MASK (0x3F)
#define PLL45XX_SDIV_MASK (0x7)
#define PLL45XX_AFC_MASK (0x1F)
#define PLL45XX_MDIV_SHIFT (16)
#define PLL45XX_PDIV_SHIFT (8)
#define PLL45XX_SDIV_SHIFT (0)
#define PLL45XX_AFC_SHIFT (0)
struct samsung_clk_pll45xx {
struct clk_hw hw;
enum pll45xx_type type;
const void __iomem *con_reg;
};
#define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
#define PLL45XX_ENABLE BIT(31)
#define PLL45XX_LOCKED BIT(29)
static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw);
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
@ -208,54 +311,113 @@ static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
return (unsigned long)fvco;
}
static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
const struct samsung_pll_rate_table *rate)
{
u32 old_mdiv, old_pdiv, old_afc;
old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK;
return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
|| old_afc != rate->afc);
}
static int samsung_pll45xx_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 con0, con1;
ktime_t start;
/* 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;
}
con0 = __raw_readl(pll->con_reg);
con1 = __raw_readl(pll->con_reg + 0x4);
if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
/* If only s change, change just s value only*/
con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
__raw_writel(con0, pll->con_reg);
return 0;
}
/* Set PLL PMS values. */
con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) |
(PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) |
(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT));
con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) |
(rate->pdiv << PLL45XX_PDIV_SHIFT) |
(rate->sdiv << PLL45XX_SDIV_SHIFT);
/* Set PLL AFC value. */
con1 = __raw_readl(pll->con_reg + 0x4);
con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
/* Set PLL lock time. */
switch (pll->type) {
case pll_4502:
__raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
break;
case pll_4508:
__raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
break;
default:
break;
};
/* Set new configuration. */
__raw_writel(con1, pll->con_reg + 0x4);
__raw_writel(con0, pll->con_reg);
/* Wait for locking. */
start = ktime_get();
while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) {
ktime_t delta = ktime_sub(ktime_get(), start);
if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
pr_err("%s: could not lock PLL %s\n",
__func__, __clk_get_name(hw->clk));
return -EFAULT;
}
cpu_relax();
}
return 0;
}
static const struct clk_ops samsung_pll45xx_clk_ops = {
.recalc_rate = samsung_pll45xx_recalc_rate,
.round_rate = samsung_pll_round_rate,
.set_rate = samsung_pll45xx_set_rate,
};
struct clk * __init samsung_clk_register_pll45xx(const char *name,
const char *pname, const void __iomem *con_reg,
enum pll45xx_type type)
{
struct samsung_clk_pll45xx *pll;
struct clk *clk;
struct clk_init_data init;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll) {
pr_err("%s: could not allocate pll clk %s\n", __func__, name);
return NULL;
}
init.name = name;
init.ops = &samsung_pll45xx_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE;
init.parent_names = &pname;
init.num_parents = 1;
pll->hw.init = &init;
pll->con_reg = con_reg;
pll->type = type;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s\n", __func__,
name);
kfree(pll);
}
if (clk_register_clkdev(clk, name, NULL))
pr_err("%s: failed to register lookup for %s", __func__, name);
return clk;
}
static const struct clk_ops samsung_pll45xx_clk_min_ops = {
.recalc_rate = samsung_pll45xx_recalc_rate,
};
/*
* PLL46xx Clock Type
*/
#define PLL46XX_LOCK_FACTOR 3000
#define PLL46XX_VSEL_MASK (1)
#define PLL46XX_MDIV_MASK (0x1FF)
#define PLL46XX_PDIV_MASK (0x3F)
#define PLL46XX_SDIV_MASK (0x7)
#define PLL46XX_VSEL_SHIFT (27)
#define PLL46XX_MDIV_SHIFT (16)
#define PLL46XX_PDIV_SHIFT (8)
#define PLL46XX_SDIV_SHIFT (0)
@ -263,19 +425,20 @@ struct clk * __init samsung_clk_register_pll45xx(const char *name,
#define PLL46XX_KDIV_MASK (0xFFFF)
#define PLL4650C_KDIV_MASK (0xFFF)
#define PLL46XX_KDIV_SHIFT (0)
#define PLL46XX_MFR_MASK (0x3F)
#define PLL46XX_MRR_MASK (0x1F)
#define PLL46XX_KDIV_SHIFT (0)
#define PLL46XX_MFR_SHIFT (16)
#define PLL46XX_MRR_SHIFT (24)
struct samsung_clk_pll46xx {
struct clk_hw hw;
enum pll46xx_type type;
const void __iomem *con_reg;
};
#define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw)
#define PLL46XX_ENABLE BIT(31)
#define PLL46XX_LOCKED BIT(29)
#define PLL46XX_VSEL BIT(27)
static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw);
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
u64 fvco = parent_rate;
@ -295,47 +458,175 @@ static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
return (unsigned long)fvco;
}
static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
const struct samsung_pll_rate_table *rate)
{
u32 old_mdiv, old_pdiv, old_kdiv;
old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK;
return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
|| old_kdiv != rate->kdiv);
}
static int samsung_pll46xx_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 con0, con1, lock;
ktime_t start;
/* 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;
}
con0 = __raw_readl(pll->con_reg);
con1 = __raw_readl(pll->con_reg + 0x4);
if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
/* If only s change, change just s value only*/
con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
__raw_writel(con0, pll->con_reg);
return 0;
}
/* Set PLL lock time. */
lock = rate->pdiv * PLL46XX_LOCK_FACTOR;
if (lock > 0xffff)
/* Maximum lock time bitfield is 16-bit. */
lock = 0xffff;
/* Set PLL PMS and VSEL values. */
con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
(PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
(PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
(rate->pdiv << PLL46XX_PDIV_SHIFT) |
(rate->sdiv << PLL46XX_SDIV_SHIFT) |
(rate->vsel << PLL46XX_VSEL_SHIFT);
/* Set PLL K, MFR and MRR values. */
con1 = __raw_readl(pll->con_reg + 0x4);
con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
(PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) |
(rate->mfr << PLL46XX_MFR_SHIFT) |
(rate->mrr << PLL46XX_MRR_SHIFT);
/* Write configuration to PLL */
__raw_writel(lock, pll->lock_reg);
__raw_writel(con0, pll->con_reg);
__raw_writel(con1, pll->con_reg + 0x4);
/* Wait for locking. */
start = ktime_get();
while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) {
ktime_t delta = ktime_sub(ktime_get(), start);
if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
pr_err("%s: could not lock PLL %s\n",
__func__, __clk_get_name(hw->clk));
return -EFAULT;
}
cpu_relax();
}
return 0;
}
static const struct clk_ops samsung_pll46xx_clk_ops = {
.recalc_rate = samsung_pll46xx_recalc_rate,
.round_rate = samsung_pll_round_rate,
.set_rate = samsung_pll46xx_set_rate,
};
static const struct clk_ops samsung_pll46xx_clk_min_ops = {
.recalc_rate = samsung_pll46xx_recalc_rate,
};
struct clk * __init samsung_clk_register_pll46xx(const char *name,
const char *pname, const void __iomem *con_reg,
enum pll46xx_type type)
/*
* PLL6552 Clock Type
*/
#define PLL6552_MDIV_MASK 0x3ff
#define PLL6552_PDIV_MASK 0x3f
#define PLL6552_SDIV_MASK 0x7
#define PLL6552_MDIV_SHIFT 16
#define PLL6552_PDIV_SHIFT 8
#define PLL6552_SDIV_SHIFT 0
static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct samsung_clk_pll46xx *pll;
struct clk *clk;
struct clk_init_data init;
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll) {
pr_err("%s: could not allocate pll clk %s\n", __func__, name);
return NULL;
}
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;
sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
init.name = name;
init.ops = &samsung_pll46xx_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE;
init.parent_names = &pname;
init.num_parents = 1;
fvco *= mdiv;
do_div(fvco, (pdiv << sdiv));
pll->hw.init = &init;
pll->con_reg = con_reg;
pll->type = type;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s\n", __func__,
name);
kfree(pll);
}
if (clk_register_clkdev(clk, name, NULL))
pr_err("%s: failed to register lookup for %s", __func__, name);
return clk;
return (unsigned long)fvco;
}
static const struct clk_ops samsung_pll6552_clk_ops = {
.recalc_rate = samsung_pll6552_recalc_rate,
};
/*
* PLL6553 Clock Type
*/
#define PLL6553_MDIV_MASK 0xff
#define PLL6553_PDIV_MASK 0x3f
#define PLL6553_SDIV_MASK 0x7
#define PLL6553_KDIV_MASK 0xffff
#define PLL6553_MDIV_SHIFT 16
#define PLL6553_PDIV_SHIFT 8
#define PLL6553_SDIV_SHIFT 0
#define PLL6553_KDIV_SHIFT 0
static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
u64 fvco = parent_rate;
pll_con0 = __raw_readl(pll->con_reg);
pll_con1 = __raw_readl(pll->con_reg + 0x4);
mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK;
fvco *= (mdiv << 16) + kdiv;
do_div(fvco, (pdiv << sdiv));
fvco >>= 16;
return (unsigned long)fvco;
}
static const struct clk_ops samsung_pll6553_clk_ops = {
.recalc_rate = samsung_pll6553_recalc_rate,
};
/*
* PLL2550x Clock Type
*/
@ -418,3 +709,117 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
return clk;
}
static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
void __iomem *base)
{
struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
int ret, len;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll) {
pr_err("%s: could not allocate pll clk %s\n",
__func__, pll_clk->name);
return;
}
init.name = pll_clk->name;
init.flags = pll_clk->flags;
init.parent_names = &pll_clk->parent_name;
init.num_parents = 1;
if (pll_clk->rate_table) {
/* find count of rates in rate_table */
for (len = 0; pll_clk->rate_table[len].rate != 0; )
len++;
pll->rate_count = len;
pll->rate_table = kmemdup(pll_clk->rate_table,
pll->rate_count *
sizeof(struct samsung_pll_rate_table),
GFP_KERNEL);
WARN(!pll->rate_table,
"%s: could not allocate rate table for %s\n",
__func__, pll_clk->name);
}
switch (pll_clk->type) {
/* clk_ops for 35xx and 2550 are similar */
case pll_35xx:
case pll_2550:
if (!pll->rate_table)
init.ops = &samsung_pll35xx_clk_min_ops;
else
init.ops = &samsung_pll35xx_clk_ops;
break;
case pll_4500:
init.ops = &samsung_pll45xx_clk_min_ops;
break;
case pll_4502:
case pll_4508:
if (!pll->rate_table)
init.ops = &samsung_pll45xx_clk_min_ops;
else
init.ops = &samsung_pll45xx_clk_ops;
break;
/* clk_ops for 36xx and 2650 are similar */
case pll_36xx:
case pll_2650:
if (!pll->rate_table)
init.ops = &samsung_pll36xx_clk_min_ops;
else
init.ops = &samsung_pll36xx_clk_ops;
break;
case pll_6552:
init.ops = &samsung_pll6552_clk_ops;
break;
case pll_6553:
init.ops = &samsung_pll6553_clk_ops;
break;
case pll_4600:
case pll_4650:
case pll_4650c:
if (!pll->rate_table)
init.ops = &samsung_pll46xx_clk_min_ops;
else
init.ops = &samsung_pll46xx_clk_ops;
break;
default:
pr_warn("%s: Unknown pll type for pll clk %s\n",
__func__, pll_clk->name);
}
pll->hw.init = &init;
pll->type = pll_clk->type;
pll->lock_reg = base + pll_clk->lock_offset;
pll->con_reg = base + pll_clk->con_offset;
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s : %ld\n",
__func__, pll_clk->name, PTR_ERR(clk));
kfree(pll);
return;
}
samsung_clk_add_lookup(clk, pll_clk->id);
if (!pll_clk->alias)
return;
ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
if (ret)
pr_err("%s: failed to register lookup for %s : %d",
__func__, pll_clk->name, ret);
}
void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
unsigned int nr_pll, void __iomem *base)
{
int cnt;
for (cnt = 0; cnt < nr_pll; cnt++)
_samsung_clk_register_pll(&pll_list[cnt], base);
}

View File

@ -12,28 +12,83 @@
#ifndef __SAMSUNG_CLK_PLL_H
#define __SAMSUNG_CLK_PLL_H
enum pll45xx_type {
enum samsung_pll_type {
pll_35xx,
pll_36xx,
pll_2550,
pll_2650,
pll_4500,
pll_4502,
pll_4508
};
enum pll46xx_type {
pll_4508,
pll_4600,
pll_4650,
pll_4650c,
pll_6552,
pll_6553,
};
#define PLL_35XX_RATE(_rate, _m, _p, _s) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
}
#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
}
#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.afc = (_afc), \
}
#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
.vsel = (_vsel), \
}
#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
{ \
.rate = (_rate), \
.mdiv = (_m), \
.pdiv = (_p), \
.sdiv = (_s), \
.kdiv = (_k), \
.mfr = (_mfr), \
.mrr = (_mrr), \
.vsel = (_vsel), \
}
/* NOTE: Rate table should be kept sorted in descending order. */
struct samsung_pll_rate_table {
unsigned int rate;
unsigned int pdiv;
unsigned int mdiv;
unsigned int sdiv;
unsigned int kdiv;
unsigned int afc;
unsigned int mfr;
unsigned int mrr;
unsigned int vsel;
};
extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
const char *pname, const void __iomem *con_reg);
extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
const char *pname, const void __iomem *con_reg);
extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
const char *pname, const void __iomem *con_reg,
enum pll45xx_type type);
extern struct clk * __init samsung_clk_register_pll46xx(const char *name,
const char *pname, const void __iomem *con_reg,
enum pll46xx_type type);
extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
const char *pname, const void __iomem *reg_base,
const unsigned long offset);

View File

@ -0,0 +1,473 @@
/*
* Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Common Clock Framework support for all S3C64xx SoCs.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
#include "clk.h"
#include "clk-pll.h"
/* S3C64xx clock controller register offsets. */
#define APLL_LOCK 0x000
#define MPLL_LOCK 0x004
#define EPLL_LOCK 0x008
#define APLL_CON 0x00c
#define MPLL_CON 0x010
#define EPLL_CON0 0x014
#define EPLL_CON1 0x018
#define CLK_SRC 0x01c
#define CLK_DIV0 0x020
#define CLK_DIV1 0x024
#define CLK_DIV2 0x028
#define HCLK_GATE 0x030
#define PCLK_GATE 0x034
#define SCLK_GATE 0x038
#define MEM0_GATE 0x03c
#define CLK_SRC2 0x10c
#define OTHERS 0x900
/* Helper macros to define clock arrays. */
#define FIXED_RATE_CLOCKS(name) \
static struct samsung_fixed_rate_clock name[]
#define MUX_CLOCKS(name) \
static struct samsung_mux_clock name[]
#define DIV_CLOCKS(name) \
static struct samsung_div_clock name[]
#define GATE_CLOCKS(name) \
static struct samsung_gate_clock name[]
/* Helper macros for gate types present on S3C64xx. */
#define GATE_BUS(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, 0, 0)
#define GATE_SCLK(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
#define GATE_ON(_id, cname, pname, o, b) \
GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
/* list of PLLs to be registered */
enum s3c64xx_plls {
apll, mpll, epll,
};
/*
* List of controller registers to be saved and restored during
* a suspend/resume cycle.
*/
static unsigned long s3c64xx_clk_regs[] __initdata = {
APLL_LOCK,
MPLL_LOCK,
EPLL_LOCK,
APLL_CON,
MPLL_CON,
EPLL_CON0,
EPLL_CON1,
CLK_SRC,
CLK_DIV0,
CLK_DIV1,
CLK_DIV2,
HCLK_GATE,
PCLK_GATE,
SCLK_GATE,
};
static unsigned long s3c6410_clk_regs[] __initdata = {
CLK_SRC2,
MEM0_GATE,
};
/* List of parent clocks common for all S3C64xx SoCs. */
PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
PNAME(uart_p) = { "mout_epll", "dout_mpll" };
PNAME(audio0_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk0",
"pcmcdclk0", "none", "none", "none" };
PNAME(audio1_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1",
"pcmcdclk0", "none", "none", "none" };
PNAME(mfc_p) = { "hclkx2", "mout_epll" };
PNAME(apll_p) = { "fin_pll", "fout_apll" };
PNAME(mpll_p) = { "fin_pll", "fout_mpll" };
PNAME(epll_p) = { "fin_pll", "fout_epll" };
PNAME(hclkx2_p) = { "mout_mpll", "mout_apll" };
/* S3C6400-specific parent clocks. */
PNAME(scaler_lcd_p6400) = { "mout_epll", "dout_mpll", "none", "none" };
PNAME(irda_p6400) = { "mout_epll", "dout_mpll", "none", "clk48m" };
PNAME(uhost_p6400) = { "clk48m", "mout_epll", "dout_mpll", "none" };
/* S3C6410-specific parent clocks. */
PNAME(clk27_p6410) = { "clk27m", "fin_pll" };
PNAME(scaler_lcd_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "none" };
PNAME(irda_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "clk48m" };
PNAME(uhost_p6410) = { "clk48m", "mout_epll", "dout_mpll", "fin_pll" };
PNAME(audio2_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2",
"pcmcdclk1", "none", "none", "none" };
/* Fixed rate clocks generated outside the SoC. */
FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
FRATE(0, "fin_pll", NULL, CLK_IS_ROOT, 0),
FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
};
/* Fixed rate clocks generated inside the SoC. */
FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
};
/* List of clock muxes present on all S3C64xx SoCs. */
MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
MUX_F(0, "mout_syncmux", hclkx2_p, OTHERS, 6, 1, 0, CLK_MUX_READ_ONLY),
MUX(MOUT_APLL, "mout_apll", apll_p, CLK_SRC, 0, 1),
MUX(MOUT_MPLL, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
MUX(MOUT_MFC, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
MUX(MOUT_AUDIO0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
MUX(MOUT_AUDIO1, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
MUX(MOUT_UART, "mout_uart", uart_p, CLK_SRC, 13, 1),
MUX(MOUT_SPI0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
MUX(MOUT_SPI1, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
MUX(MOUT_MMC0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
MUX(MOUT_MMC1, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
MUX(MOUT_MMC2, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
};
/* List of clock muxes present on S3C6400. */
MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
MUX(MOUT_UHOST, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
MUX(MOUT_IRDA, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
};
/* List of clock muxes present on S3C6410. */
MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
MUX(MOUT_UHOST, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
MUX(MOUT_IRDA, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
MUX(MOUT_DAC27, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
MUX(MOUT_TV27, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
MUX(MOUT_AUDIO2, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
};
/* List of clock dividers present on all S3C64xx SoCs. */
DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
DIV(HCLKX2, "hclkx2", "mout_syncmux", CLK_DIV0, 9, 3),
DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
DIV(DOUT_SECUR, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
DIV(DOUT_CAM, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
DIV(DOUT_JPEG, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
DIV(DOUT_LCD, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
DIV(DOUT_SCALER, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
DIV(DOUT_UHOST, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
DIV(DOUT_UART, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
DIV(DOUT_IRDA, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
};
/* List of clock dividers present on S3C6400. */
DIV_CLOCKS(s3c6400_div_clks) __initdata = {
DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
};
/* List of clock dividers present on S3C6410. */
DIV_CLOCKS(s3c6410_div_clks) __initdata = {
DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
DIV(DOUT_FIMC, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
};
/* List of clock gates present on all S3C64xx SoCs. */
GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE, 30),
GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m", SCLK_GATE, 29),
GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48", "clk48m", SCLK_GATE, 28),
GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48", "clk48m", SCLK_GATE, 27),
GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26),
GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25),
GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24),
GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE, 22),
GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1", SCLK_GATE, 21),
GATE_SCLK(SCLK_SPI0, "sclk_spi0", "dout_spi0", SCLK_GATE, 20),
GATE_SCLK(SCLK_DAC27, "sclk_dac27", "mout_dac27", SCLK_GATE, 19),
GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18),
GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler", SCLK_GATE, 16),
GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m", SCLK_GATE, 15),
GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd", SCLK_GATE, 14),
GATE_SCLK(SCLK_POST0_27, "sclk_post0_27", "clk27m", SCLK_GATE, 12),
GATE_SCLK(SCLK_POST0, "sclk_post0", "dout_lcd", SCLK_GATE, 10),
GATE_SCLK(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", SCLK_GATE, 9),
GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8),
GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE, 7),
GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE, 6),
GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE, 5),
GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE, 3),
GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE, 2),
GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE, 1),
};
/* List of clock gates present on S3C6400. */
GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE, 4),
};
/* List of clock gates present on S3C6410. */
GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", SCLK_GATE, 11),
GATE_BUS(MEM0_CFCON, "mem0_cfcon", "hclk_mem0", MEM0_GATE, 5),
GATE_BUS(MEM0_ONENAND1, "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4),
GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE, 2),
GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE, 1),
};
/* List of PLL clocks. */
static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = {
[apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
APLL_LOCK, APLL_CON, NULL),
[mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
MPLL_LOCK, MPLL_CON, NULL),
[epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
EPLL_LOCK, EPLL_CON0, NULL),
};
/* Aliases for common s3c64xx clocks. */
static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
ALIAS(FOUT_APLL, NULL, "fout_apll"),
ALIAS(FOUT_MPLL, NULL, "fout_mpll"),
ALIAS(FOUT_EPLL, NULL, "fout_epll"),
ALIAS(MOUT_EPLL, NULL, "mout_epll"),
ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
ALIAS(HCLKX2, NULL, "hclk2"),
ALIAS(HCLK, NULL, "hclk"),
ALIAS(PCLK, NULL, "pclk"),
ALIAS(PCLK, NULL, "clk_uart_baud2"),
ALIAS(ARMCLK, NULL, "armclk"),
ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
ALIAS(HCLK_DMA1, NULL, "dma1"),
ALIAS(HCLK_DMA0, NULL, "dma0"),
ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
ALIAS(PCLK_PWM, NULL, "timers"),
ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
ALIAS(PCLK_WDT, NULL, "watchdog"),
ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"),
ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"),
ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"),
ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"),
ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"),
ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"),
ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"),
ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"),
ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
ALIAS(SCLK_CAM, "s3c-camif", "camera"),
};
/* Aliases for s3c6400-specific clocks. */
static struct samsung_clock_alias s3c6400_clock_aliases[] = {
/* Nothing to place here yet. */
};
/* Aliases for s3c6410-specific clocks. */
static struct samsung_clock_alias s3c6410_clock_aliases[] = {
ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
ALIAS(MEM0_SROM, NULL, "srom"),
};
static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f,
unsigned long xusbxti_f)
{
s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f;
s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks,
ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
}
/* Register s3c64xx clocks. */
void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
unsigned long xusbxti_f, bool is_s3c6400,
void __iomem *reg_base)
{
unsigned long *soc_regs = NULL;
unsigned long nr_soc_regs = 0;
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
}
if (!is_s3c6400) {
soc_regs = s3c6410_clk_regs;
nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
}
samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs);
/* Register external clocks. */
if (!np)
s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f);
/* Register PLLs. */
samsung_clk_register_pll(s3c64xx_pll_clks,
ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
/* Register common internal clocks. */
samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks,
ARRAY_SIZE(s3c64xx_fixed_rate_clks));
samsung_clk_register_mux(s3c64xx_mux_clks,
ARRAY_SIZE(s3c64xx_mux_clks));
samsung_clk_register_div(s3c64xx_div_clks,
ARRAY_SIZE(s3c64xx_div_clks));
samsung_clk_register_gate(s3c64xx_gate_clks,
ARRAY_SIZE(s3c64xx_gate_clks));
/* Register SoC-specific clocks. */
if (is_s3c6400) {
samsung_clk_register_mux(s3c6400_mux_clks,
ARRAY_SIZE(s3c6400_mux_clks));
samsung_clk_register_div(s3c6400_div_clks,
ARRAY_SIZE(s3c6400_div_clks));
samsung_clk_register_gate(s3c6400_gate_clks,
ARRAY_SIZE(s3c6400_gate_clks));
samsung_clk_register_alias(s3c6400_clock_aliases,
ARRAY_SIZE(s3c6400_clock_aliases));
} else {
samsung_clk_register_mux(s3c6410_mux_clks,
ARRAY_SIZE(s3c6410_mux_clks));
samsung_clk_register_div(s3c6410_div_clks,
ARRAY_SIZE(s3c6410_div_clks));
samsung_clk_register_gate(s3c6410_gate_clks,
ARRAY_SIZE(s3c6410_gate_clks));
samsung_clk_register_alias(s3c6410_clock_aliases,
ARRAY_SIZE(s3c6410_clock_aliases));
}
samsung_clk_register_alias(s3c64xx_clock_aliases,
ARRAY_SIZE(s3c64xx_clock_aliases));
pr_info("%s clocks: apll = %lu, mpll = %lu\n"
"\tepll = %lu, arm_clk = %lu\n",
is_s3c6400 ? "S3C6400" : "S3C6410",
_get_rate("fout_apll"), _get_rate("fout_mpll"),
_get_rate("fout_epll"), _get_rate("armclk"));
}
static void __init s3c6400_clk_init(struct device_node *np)
{
s3c64xx_clk_init(np, 0, 0, true, NULL);
}
CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock", s3c6400_clk_init);
static void __init s3c6410_clk_init(struct device_node *np)
{
s3c64xx_clk_init(np, 0, 0, false, NULL);
}
CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock", s3c6410_clk_init);

View File

@ -307,14 +307,12 @@ void __init samsung_clk_of_register_fixed_ext(
unsigned long _get_rate(const char *clk_name)
{
struct clk *clk;
unsigned long rate;
clk = clk_get(NULL, clk_name);
if (IS_ERR(clk)) {
clk = __clk_lookup(clk_name);
if (!clk) {
pr_err("%s: could not find clock %s\n", __func__, clk_name);
return 0;
}
rate = clk_get_rate(clk);
clk_put(clk);
return rate;
return clk_get_rate(clk);
}

View File

@ -19,6 +19,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include "clk-pll.h"
/**
* struct samsung_clock_alias: information about mux clock
@ -39,6 +40,8 @@ struct samsung_clock_alias {
.alias = a, \
}
#define MHZ (1000 * 1000)
/**
* struct samsung_fixed_rate_clock: information about fixed-rate clock
* @id: platform specific id of the clock.
@ -127,7 +130,7 @@ struct samsung_mux_clock {
.name = cname, \
.parent_names = pnames, \
.num_parents = ARRAY_SIZE(pnames), \
.flags = f, \
.flags = (f) | CLK_SET_RATE_NO_REPARENT, \
.offset = o, \
.shift = s, \
.width = w, \
@ -261,6 +264,54 @@ struct samsung_clk_reg_dump {
u32 value;
};
/**
* struct samsung_pll_clock: information about pll clock
* @id: platform specific id of the clock.
* @dev_name: name of the device to which this clock belongs.
* @name: name of this pll clock.
* @parent_name: name of the parent clock.
* @flags: optional flags for basic clock.
* @con_offset: offset of the register for configuring the PLL.
* @lock_offset: offset of the register for locking the PLL.
* @type: Type of PLL to be registered.
* @alias: optional clock alias name to be assigned to this clock.
*/
struct samsung_pll_clock {
unsigned int id;
const char *dev_name;
const char *name;
const char *parent_name;
unsigned long flags;
int con_offset;
int lock_offset;
enum samsung_pll_type type;
const struct samsung_pll_rate_table *rate_table;
const char *alias;
};
#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \
_rtable, _alias) \
{ \
.id = _id, \
.type = _typ, \
.dev_name = _dname, \
.name = _name, \
.parent_name = _pname, \
.flags = CLK_GET_RATE_NOCACHE, \
.con_offset = _con, \
.lock_offset = _lock, \
.rate_table = _rtable, \
.alias = _alias, \
}
#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
_lock, _con, _rtable, _name)
#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
_lock, _con, _rtable, _alias)
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
unsigned long nr_clks, unsigned long *rdump,
unsigned long nr_rdump, unsigned long *soc_rdump,
@ -284,6 +335,8 @@ extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_gate(
struct samsung_gate_clock *clk_list, unsigned int nr_clk);
extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
unsigned int nr_clk, void __iomem *base);
extern unsigned long _get_rate(const char *clk_name);

View File

@ -416,9 +416,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
/* clock derived from 24 or 25 MHz osc clk */
/* vco-pll */
clk = clk_register_mux(NULL, "vco1_mclk", vco_parents,
ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG,
SPEAR1310_PLL1_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PLL_CFG, SPEAR1310_PLL1_CLK_SHIFT,
SPEAR1310_PLL_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "vco1_mclk", NULL);
clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk",
0, SPEAR1310_PLL1_CTR, SPEAR1310_PLL1_FRQ, pll_rtbl,
@ -427,9 +427,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk1, "pll1_clk", NULL);
clk = clk_register_mux(NULL, "vco2_mclk", vco_parents,
ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG,
SPEAR1310_PLL2_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PLL_CFG, SPEAR1310_PLL2_CLK_SHIFT,
SPEAR1310_PLL_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "vco2_mclk", NULL);
clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk",
0, SPEAR1310_PLL2_CTR, SPEAR1310_PLL2_FRQ, pll_rtbl,
@ -438,9 +438,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk1, "pll2_clk", NULL);
clk = clk_register_mux(NULL, "vco3_mclk", vco_parents,
ARRAY_SIZE(vco_parents), 0, SPEAR1310_PLL_CFG,
SPEAR1310_PLL3_CLK_SHIFT, SPEAR1310_PLL_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PLL_CFG, SPEAR1310_PLL3_CLK_SHIFT,
SPEAR1310_PLL_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "vco3_mclk", NULL);
clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk",
0, SPEAR1310_PLL3_CTR, SPEAR1310_PLL3_FRQ, pll_rtbl,
@ -515,9 +515,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
/* gpt clocks */
clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
SPEAR1310_GPT0_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT0_CLK_SHIFT,
SPEAR1310_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt0_mclk", NULL);
clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT0_CLK_ENB, 0,
@ -525,9 +525,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "gpt0");
clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
SPEAR1310_GPT1_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT1_CLK_SHIFT,
SPEAR1310_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mclk", NULL);
clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT1_CLK_ENB, 0,
@ -535,9 +535,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "gpt1");
clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
SPEAR1310_GPT2_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT2_CLK_SHIFT,
SPEAR1310_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mclk", NULL);
clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT2_CLK_ENB, 0,
@ -545,9 +545,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "gpt2");
clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1310_PERIP_CLK_CFG,
SPEAR1310_GPT3_CLK_SHIFT, SPEAR1310_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT3_CLK_SHIFT,
SPEAR1310_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt3_mclk", NULL);
clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT3_CLK_ENB, 0,
@ -562,7 +562,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart0_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_UART_CLK_SHIFT,
SPEAR1310_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart0_mclk", NULL);
@ -602,7 +603,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(c3_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_C3_CLK_SHIFT,
SPEAR1310_C3_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "c3_mclk", NULL);
@ -614,8 +616,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
/* gmac */
clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
ARRAY_SIZE(gmac_phy_input_parents), 0,
SPEAR1310_GMAC_CLK_CFG,
ARRAY_SIZE(gmac_phy_input_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1310_GMAC_CLK_CFG,
SPEAR1310_GMAC_PHY_INPUT_CLK_SHIFT,
SPEAR1310_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "phy_input_mclk", NULL);
@ -627,15 +629,16 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk1, "phy_syn_gclk", NULL);
clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents,
ARRAY_SIZE(gmac_phy_parents), 0,
ARRAY_SIZE(gmac_phy_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT,
SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "stmmacphy.0", NULL);
/* clcd */
clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
ARRAY_SIZE(clcd_synth_parents), 0,
SPEAR1310_CLCD_CLK_SYNT, SPEAR1310_CLCD_SYNT_CLK_SHIFT,
ARRAY_SIZE(clcd_synth_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1310_CLCD_CLK_SYNT,
SPEAR1310_CLCD_SYNT_CLK_SHIFT,
SPEAR1310_CLCD_SYNT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "clcd_syn_mclk", NULL);
@ -645,7 +648,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, "clcd_syn_clk", NULL);
clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(clcd_pixel_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT,
SPEAR1310_CLCD_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
@ -657,9 +661,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
/* i2s */
clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
ARRAY_SIZE(i2s_src_parents), 0, SPEAR1310_I2S_CLK_CFG,
SPEAR1310_I2S_SRC_CLK_SHIFT, SPEAR1310_I2S_SRC_CLK_MASK,
0, &_lock);
ARRAY_SIZE(i2s_src_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_SRC_CLK_SHIFT,
SPEAR1310_I2S_SRC_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_src_mclk", NULL);
clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
@ -668,7 +672,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(i2s_ref_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_REF_SHIFT,
SPEAR1310_I2S_REF_SEL_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
@ -806,13 +811,15 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
/* RAS clks */
clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents,
ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1310_PLL_CFG,
ARRAY_SIZE(gen_synth0_1_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1310_PLL_CFG,
SPEAR1310_RAS_SYNT0_1_CLK_SHIFT,
SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1310_PLL_CFG,
ARRAY_SIZE(gen_synth2_3_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1310_PLL_CFG,
SPEAR1310_RAS_SYNT2_3_CLK_SHIFT,
SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
@ -929,8 +936,8 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk = clk_register_mux(NULL, "smii_rgmii_phy_mclk",
smii_rgmii_phy_parents,
ARRAY_SIZE(smii_rgmii_phy_parents), 0,
SPEAR1310_RAS_CTRL_REG1,
ARRAY_SIZE(smii_rgmii_phy_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1310_RAS_CTRL_REG1,
SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT,
SPEAR1310_PHY_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "stmmacphy.1", NULL);
@ -938,15 +945,15 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, "stmmacphy.4", NULL);
clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents,
ARRAY_SIZE(rmii_phy_parents), 0,
ARRAY_SIZE(rmii_phy_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT,
SPEAR1310_PHY_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "stmmacphy.3", NULL);
clk = clk_register_mux(NULL, "uart1_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_UART1_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
0, &_lock);
ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART1_CLK_SHIFT,
SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart1_mclk", NULL);
clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0,
@ -955,9 +962,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5c800000.serial");
clk = clk_register_mux(NULL, "uart2_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_UART2_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
0, &_lock);
ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART2_CLK_SHIFT,
SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart2_mclk", NULL);
clk = clk_register_gate(NULL, "uart2_clk", "uart2_mclk", 0,
@ -966,9 +973,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5c900000.serial");
clk = clk_register_mux(NULL, "uart3_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_UART3_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
0, &_lock);
ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART3_CLK_SHIFT,
SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart3_mclk", NULL);
clk = clk_register_gate(NULL, "uart3_clk", "uart3_mclk", 0,
@ -977,9 +984,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5ca00000.serial");
clk = clk_register_mux(NULL, "uart4_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_UART4_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
0, &_lock);
ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART4_CLK_SHIFT,
SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart4_mclk", NULL);
clk = clk_register_gate(NULL, "uart4_clk", "uart4_mclk", 0,
@ -988,9 +995,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5cb00000.serial");
clk = clk_register_mux(NULL, "uart5_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_UART5_CLK_SHIFT, SPEAR1310_RAS_UART_CLK_MASK,
0, &_lock);
ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART5_CLK_SHIFT,
SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart5_mclk", NULL);
clk = clk_register_gate(NULL, "uart5_clk", "uart5_mclk", 0,
@ -999,9 +1006,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5cc00000.serial");
clk = clk_register_mux(NULL, "i2c1_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C1_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C1_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c1_mclk", NULL);
clk = clk_register_gate(NULL, "i2c1_clk", "i2c1_mclk", 0,
@ -1010,9 +1017,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5cd00000.i2c");
clk = clk_register_mux(NULL, "i2c2_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C2_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C2_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c2_mclk", NULL);
clk = clk_register_gate(NULL, "i2c2_clk", "i2c2_mclk", 0,
@ -1021,9 +1028,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5ce00000.i2c");
clk = clk_register_mux(NULL, "i2c3_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C3_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C3_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c3_mclk", NULL);
clk = clk_register_gate(NULL, "i2c3_clk", "i2c3_mclk", 0,
@ -1032,9 +1039,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5cf00000.i2c");
clk = clk_register_mux(NULL, "i2c4_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C4_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C4_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c4_mclk", NULL);
clk = clk_register_gate(NULL, "i2c4_clk", "i2c4_mclk", 0,
@ -1043,9 +1050,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5d000000.i2c");
clk = clk_register_mux(NULL, "i2c5_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C5_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C5_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c5_mclk", NULL);
clk = clk_register_gate(NULL, "i2c5_clk", "i2c5_mclk", 0,
@ -1054,9 +1061,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5d100000.i2c");
clk = clk_register_mux(NULL, "i2c6_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C6_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C6_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c6_mclk", NULL);
clk = clk_register_gate(NULL, "i2c6_clk", "i2c6_mclk", 0,
@ -1065,9 +1072,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5d200000.i2c");
clk = clk_register_mux(NULL, "i2c7_mclk", i2c_parents,
ARRAY_SIZE(i2c_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_I2C7_CLK_SHIFT, SPEAR1310_I2C_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C7_CLK_SHIFT,
SPEAR1310_I2C_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2c7_mclk", NULL);
clk = clk_register_gate(NULL, "i2c7_clk", "i2c7_mclk", 0,
@ -1076,9 +1083,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5d300000.i2c");
clk = clk_register_mux(NULL, "ssp1_mclk", ssp1_parents,
ARRAY_SIZE(ssp1_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_SSP1_CLK_SHIFT, SPEAR1310_SSP1_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(ssp1_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_SSP1_CLK_SHIFT,
SPEAR1310_SSP1_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "ssp1_mclk", NULL);
clk = clk_register_gate(NULL, "ssp1_clk", "ssp1_mclk", 0,
@ -1087,9 +1094,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "5d400000.spi");
clk = clk_register_mux(NULL, "pci_mclk", pci_parents,
ARRAY_SIZE(pci_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_PCI_CLK_SHIFT, SPEAR1310_PCI_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(pci_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_PCI_CLK_SHIFT,
SPEAR1310_PCI_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "pci_mclk", NULL);
clk = clk_register_gate(NULL, "pci_clk", "pci_mclk", 0,
@ -1098,9 +1105,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "pci");
clk = clk_register_mux(NULL, "tdm1_mclk", tdm_parents,
ARRAY_SIZE(tdm_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_TDM1_CLK_SHIFT, SPEAR1310_TDM_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(tdm_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_TDM1_CLK_SHIFT,
SPEAR1310_TDM_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "tdm1_mclk", NULL);
clk = clk_register_gate(NULL, "tdm1_clk", "tdm1_mclk", 0,
@ -1109,9 +1116,9 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
clk_register_clkdev(clk, NULL, "tdm_hdlc.0");
clk = clk_register_mux(NULL, "tdm2_mclk", tdm_parents,
ARRAY_SIZE(tdm_parents), 0, SPEAR1310_RAS_CTRL_REG0,
SPEAR1310_TDM2_CLK_SHIFT, SPEAR1310_TDM_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(tdm_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1310_RAS_CTRL_REG0, SPEAR1310_TDM2_CLK_SHIFT,
SPEAR1310_TDM_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "tdm2_mclk", NULL);
clk = clk_register_gate(NULL, "tdm2_clk", "tdm2_mclk", 0,

View File

@ -473,9 +473,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
/* clock derived from 24 or 25 MHz osc clk */
/* vco-pll */
clk = clk_register_mux(NULL, "vco1_mclk", vco_parents,
ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG,
SPEAR1340_PLL1_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PLL_CFG, SPEAR1340_PLL1_CLK_SHIFT,
SPEAR1340_PLL_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "vco1_mclk", NULL);
clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk", 0,
SPEAR1340_PLL1_CTR, SPEAR1340_PLL1_FRQ, pll_rtbl,
@ -484,9 +484,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "pll1_clk", NULL);
clk = clk_register_mux(NULL, "vco2_mclk", vco_parents,
ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG,
SPEAR1340_PLL2_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PLL_CFG, SPEAR1340_PLL2_CLK_SHIFT,
SPEAR1340_PLL_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "vco2_mclk", NULL);
clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk", 0,
SPEAR1340_PLL2_CTR, SPEAR1340_PLL2_FRQ, pll_rtbl,
@ -495,9 +495,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "pll2_clk", NULL);
clk = clk_register_mux(NULL, "vco3_mclk", vco_parents,
ARRAY_SIZE(vco_parents), 0, SPEAR1340_PLL_CFG,
SPEAR1340_PLL3_CLK_SHIFT, SPEAR1340_PLL_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PLL_CFG, SPEAR1340_PLL3_CLK_SHIFT,
SPEAR1340_PLL_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "vco3_mclk", NULL);
clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk", 0,
SPEAR1340_PLL3_CTR, SPEAR1340_PLL3_FRQ, pll_rtbl,
@ -561,8 +561,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "amba_syn_clk", NULL);
clk = clk_register_mux(NULL, "sys_mclk", sys_parents,
ARRAY_SIZE(sys_parents), 0, SPEAR1340_SYS_CLK_CTRL,
SPEAR1340_SCLK_SRC_SEL_SHIFT,
ARRAY_SIZE(sys_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_SYS_CLK_CTRL, SPEAR1340_SCLK_SRC_SEL_SHIFT,
SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock);
clk_register_clkdev(clk, "sys_mclk", NULL);
@ -583,8 +583,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, NULL, "smp_twd");
clk = clk_register_mux(NULL, "ahb_clk", ahb_parents,
ARRAY_SIZE(ahb_parents), 0, SPEAR1340_SYS_CLK_CTRL,
SPEAR1340_HCLK_SRC_SEL_SHIFT,
ARRAY_SIZE(ahb_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_SYS_CLK_CTRL, SPEAR1340_HCLK_SRC_SEL_SHIFT,
SPEAR1340_HCLK_SRC_SEL_MASK, 0, &_lock);
clk_register_clkdev(clk, "ahb_clk", NULL);
@ -594,9 +594,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
/* gpt clocks */
clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
SPEAR1340_GPT0_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT0_CLK_SHIFT,
SPEAR1340_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt0_mclk", NULL);
clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT0_CLK_ENB, 0,
@ -604,9 +604,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, NULL, "gpt0");
clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
SPEAR1340_GPT1_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT1_CLK_SHIFT,
SPEAR1340_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mclk", NULL);
clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT1_CLK_ENB, 0,
@ -614,9 +614,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, NULL, "gpt1");
clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
SPEAR1340_GPT2_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT2_CLK_SHIFT,
SPEAR1340_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mclk", NULL);
clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT2_CLK_ENB, 0,
@ -624,9 +624,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, NULL, "gpt2");
clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents,
ARRAY_SIZE(gpt_parents), 0, SPEAR1340_PERIP_CLK_CFG,
SPEAR1340_GPT3_CLK_SHIFT, SPEAR1340_GPT_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT3_CLK_SHIFT,
SPEAR1340_GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt3_mclk", NULL);
clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT3_CLK_ENB, 0,
@ -641,7 +641,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "uart0_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart0_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART0_CLK_SHIFT,
SPEAR1340_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart0_mclk", NULL);
@ -658,9 +659,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "uart1_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart1_mclk", uart1_parents,
ARRAY_SIZE(uart1_parents), 0, SPEAR1340_PERIP_CLK_CFG,
SPEAR1340_UART1_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(uart1_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART1_CLK_SHIFT,
SPEAR1340_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart1_mclk", NULL);
clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0,
@ -698,7 +699,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(c3_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_C3_CLK_SHIFT,
SPEAR1340_C3_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "c3_mclk", NULL);
@ -710,8 +712,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
/* gmac */
clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
ARRAY_SIZE(gmac_phy_input_parents), 0,
SPEAR1340_GMAC_CLK_CFG,
ARRAY_SIZE(gmac_phy_input_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1340_GMAC_CLK_CFG,
SPEAR1340_GMAC_PHY_INPUT_CLK_SHIFT,
SPEAR1340_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "phy_input_mclk", NULL);
@ -723,15 +725,16 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "phy_syn_gclk", NULL);
clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents,
ARRAY_SIZE(gmac_phy_parents), 0,
ARRAY_SIZE(gmac_phy_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT,
SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "stmmacphy.0", NULL);
/* clcd */
clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
ARRAY_SIZE(clcd_synth_parents), 0,
SPEAR1340_CLCD_CLK_SYNT, SPEAR1340_CLCD_SYNT_CLK_SHIFT,
ARRAY_SIZE(clcd_synth_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1340_CLCD_CLK_SYNT,
SPEAR1340_CLCD_SYNT_CLK_SHIFT,
SPEAR1340_CLCD_SYNT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "clcd_syn_mclk", NULL);
@ -741,7 +744,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "clcd_syn_clk", NULL);
clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(clcd_pixel_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT,
SPEAR1340_CLCD_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
@ -753,9 +757,9 @@ void __init spear1340_clk_init(void __iomem *misc_base)
/* i2s */
clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
ARRAY_SIZE(i2s_src_parents), 0, SPEAR1340_I2S_CLK_CFG,
SPEAR1340_I2S_SRC_CLK_SHIFT, SPEAR1340_I2S_SRC_CLK_MASK,
0, &_lock);
ARRAY_SIZE(i2s_src_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_SRC_CLK_SHIFT,
SPEAR1340_I2S_SRC_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_src_mclk", NULL);
clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk",
@ -765,7 +769,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(i2s_ref_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_REF_SHIFT,
SPEAR1340_I2S_REF_SEL_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
@ -891,13 +896,15 @@ void __init spear1340_clk_init(void __iomem *misc_base)
/* RAS clks */
clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents,
ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1340_PLL_CFG,
ARRAY_SIZE(gen_synth0_1_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1340_PLL_CFG,
SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gen_syn0_1_mclk", NULL);
clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1340_PLL_CFG,
ARRAY_SIZE(gen_synth2_3_parents),
CLK_SET_RATE_NO_REPARENT, SPEAR1340_PLL_CFG,
SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gen_syn2_3_mclk", NULL);
@ -938,7 +945,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, NULL, "spear_cec.1");
clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents,
ARRAY_SIZE(spdif_out_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(spdif_out_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT,
SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "spdif_out_mclk", NULL);
@ -949,7 +957,8 @@ void __init spear1340_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, NULL, "d0000000.spdif-out");
clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents,
ARRAY_SIZE(spdif_in_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(spdif_in_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT,
SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "spdif_in_mclk", NULL);

View File

@ -294,7 +294,8 @@ static void __init spear320_clk_init(void __iomem *soc_config_base)
clk_register_clkdev(clk, NULL, "a9400000.i2s");
clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents,
ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(i2s_ref_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_CONTROL_REG, I2S_REF_PCLK_SHIFT,
I2S_REF_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_ref_clk", NULL);
@ -313,57 +314,66 @@ static void __init spear320_clk_init(void __iomem *soc_config_base)
clk_register_clkdev(clk, "hclk", "ab000000.eth");
clk = clk_register_mux(NULL, "rs485_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_EXT_CTRL_REG, SPEAR320_RS485_PCLK_SHIFT,
SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a9300000.serial");
clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents,
ARRAY_SIZE(sdhci_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(sdhci_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_CONTROL_REG, SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK,
0, &_lock);
clk_register_clkdev(clk, NULL, "70000000.sdhci");
clk = clk_register_mux(NULL, "smii_pclk", smii0_parents,
ARRAY_SIZE(smii0_parents), 0, SPEAR320_CONTROL_REG,
SMII_PCLK_SHIFT, SMII_PCLK_MASK, 0, &_lock);
ARRAY_SIZE(smii0_parents), CLK_SET_RATE_NO_REPARENT,
SPEAR320_CONTROL_REG, SMII_PCLK_SHIFT, SMII_PCLK_MASK,
0, &_lock);
clk_register_clkdev(clk, NULL, "smii_pclk");
clk = clk_register_fixed_factor(NULL, "smii_clk", "smii_pclk", 0, 1, 1);
clk_register_clkdev(clk, NULL, "smii");
clk = clk_register_mux(NULL, "uart1_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_CONTROL_REG, UART1_PCLK_SHIFT, UART1_PCLK_MASK,
0, &_lock);
clk_register_clkdev(clk, NULL, "a3000000.serial");
clk = clk_register_mux(NULL, "uart2_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_EXT_CTRL_REG, SPEAR320_UART2_PCLK_SHIFT,
SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a4000000.serial");
clk = clk_register_mux(NULL, "uart3_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_EXT_CTRL_REG, SPEAR320_UART3_PCLK_SHIFT,
SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a9100000.serial");
clk = clk_register_mux(NULL, "uart4_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_EXT_CTRL_REG, SPEAR320_UART4_PCLK_SHIFT,
SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a9200000.serial");
clk = clk_register_mux(NULL, "uart5_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_EXT_CTRL_REG, SPEAR320_UART5_PCLK_SHIFT,
SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "60000000.serial");
clk = clk_register_mux(NULL, "uart6_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uartx_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SPEAR320_EXT_CTRL_REG, SPEAR320_UART6_PCLK_SHIFT,
SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "60100000.serial");
@ -427,7 +437,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_
clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(uart0_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "uart0_mclk", NULL);
@ -444,7 +455,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_
clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
ARRAY_SIZE(firda_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(firda_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "firda_mclk", NULL);
@ -458,14 +470,16 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_
clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl,
ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
ARRAY_SIZE(gpt0_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(gpt0_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt0");
clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl,
ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents,
ARRAY_SIZE(gpt1_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(gpt1_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mclk", NULL);
clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk",
@ -476,7 +490,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_
clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl,
ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_PARENT,
ARRAY_SIZE(gpt2_parents),
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mclk", NULL);
clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk",
@ -498,9 +513,9 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_
clk_register_clkdev(clk1, "gen1_syn_gclk", NULL);
clk = clk_register_mux(NULL, "gen2_3_par_clk", gen2_3_parents,
ARRAY_SIZE(gen2_3_parents), 0, CORE_CLK_CFG,
GEN_SYNTH2_3_CLK_SHIFT, GEN_SYNTH2_3_CLK_MASK, 0,
&_lock);
ARRAY_SIZE(gen2_3_parents), CLK_SET_RATE_NO_REPARENT,
CORE_CLK_CFG, GEN_SYNTH2_3_CLK_SHIFT,
GEN_SYNTH2_3_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gen2_3_par_clk", NULL);
clk = clk_register_aux("gen2_syn_clk", "gen2_syn_gclk",
@ -540,8 +555,8 @@ void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_
clk_register_clkdev(clk, "ahbmult2_clk", NULL);
clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT,
MCTR_CLK_MASK, 0, &_lock);
ARRAY_SIZE(ddr_parents), CLK_SET_RATE_NO_REPARENT,
PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "ddr_clk", NULL);
clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",

View File

@ -169,8 +169,9 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, PERIP_CLK_CFG,
UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "uart_mclk", NULL);
clk = clk_register_gate(NULL, "uart0", "uart_mclk", 0, PERIP1_CLK_ENB,
@ -188,8 +189,9 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
ARRAY_SIZE(firda_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "firda_mclk", NULL);
clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
@ -203,8 +205,9 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk1, "clcd_syn_gclk", NULL);
clk = clk_register_mux(NULL, "clcd_mclk", clcd_parents,
ARRAY_SIZE(clcd_parents), 0, PERIP_CLK_CFG,
CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0, &_lock);
ARRAY_SIZE(clcd_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "clcd_mclk", NULL);
clk = clk_register_gate(NULL, "clcd_clk", "clcd_mclk", 0,
@ -217,13 +220,13 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "gpt0_1_syn_clk", NULL);
clk = clk_register_mux(NULL, "gpt0_mclk", gpt0_1_parents,
ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG,
GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
ARRAY_SIZE(gpt0_1_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt0");
clk = clk_register_mux(NULL, "gpt1_mclk", gpt0_1_parents,
ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG,
GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
ARRAY_SIZE(gpt0_1_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mclk", NULL);
clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
@ -235,8 +238,8 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "gpt2_syn_clk", NULL);
clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mclk", NULL);
clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
@ -248,8 +251,8 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "gpt3_syn_clk", NULL);
clk = clk_register_mux(NULL, "gpt3_mclk", gpt3_parents,
ARRAY_SIZE(gpt3_parents), 0, PERIP_CLK_CFG,
GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
ARRAY_SIZE(gpt3_parents), CLK_SET_RATE_NO_REPARENT,
PERIP_CLK_CFG, GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt3_mclk", NULL);
clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
@ -277,8 +280,8 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk_register_clkdev(clk, "ahbmult2_clk", NULL);
clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT,
MCTR_CLK_MASK, 0, &_lock);
ARRAY_SIZE(ddr_parents), CLK_SET_RATE_NO_REPARENT,
PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "ddr_clk", NULL);
clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",

View File

@ -25,12 +25,12 @@
static DEFINE_SPINLOCK(clk_lock);
/**
* sunxi_osc_clk_setup() - Setup function for gatable oscillator
* sun4i_osc_clk_setup() - Setup function for gatable oscillator
*/
#define SUNXI_OSC24M_GATE 0
static void __init sunxi_osc_clk_setup(struct device_node *node)
static void __init sun4i_osc_clk_setup(struct device_node *node)
{
struct clk *clk;
struct clk_fixed_rate *fixed;
@ -64,22 +64,23 @@ static void __init sunxi_osc_clk_setup(struct device_node *node)
&gate->hw, &clk_gate_ops,
CLK_IS_ROOT);
if (clk) {
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, clk_name, NULL);
}
}
CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup);
/**
* sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1
* sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1
* PLL1 rate is calculated as follows
* rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
* parent_rate is always 24Mhz
*/
static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate,
static void sun4i_get_pll1_factors(u32 *freq, u32 parent_rate,
u8 *n, u8 *k, u8 *m, u8 *p)
{
u8 div;
@ -124,15 +125,97 @@ static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate,
*n = div / 4;
}
/**
* sun6i_a31_get_pll1_factors() - calculates n, k and m factors for PLL1
* PLL1 rate is calculated as follows
* rate = parent_rate * (n + 1) * (k + 1) / (m + 1);
* parent_rate should always be 24MHz
*/
static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
u8 *n, u8 *k, u8 *m, u8 *p)
{
/*
* We can operate only on MHz, this will make our life easier
* later.
*/
u32 freq_mhz = *freq / 1000000;
u32 parent_freq_mhz = parent_rate / 1000000;
/*
* Round down the frequency to the closest multiple of either
* 6 or 16
*/
u32 round_freq_6 = round_down(freq_mhz, 6);
u32 round_freq_16 = round_down(freq_mhz, 16);
if (round_freq_6 > round_freq_16)
freq_mhz = round_freq_6;
else
freq_mhz = round_freq_16;
*freq = freq_mhz * 1000000;
/*
* If the factors pointer are null, we were just called to
* round down the frequency.
* Exit.
*/
if (n == NULL)
return;
/* If the frequency is a multiple of 32 MHz, k is always 3 */
if (!(freq_mhz % 32))
*k = 3;
/* If the frequency is a multiple of 9 MHz, k is always 2 */
else if (!(freq_mhz % 9))
*k = 2;
/* If the frequency is a multiple of 8 MHz, k is always 1 */
else if (!(freq_mhz % 8))
*k = 1;
/* Otherwise, we don't use the k factor */
else
*k = 0;
/*
* If the frequency is a multiple of 2 but not a multiple of
* 3, m is 3. This is the first time we use 6 here, yet we
* will use it on several other places.
* We use this number because it's the lowest frequency we can
* generate (with n = 0, k = 0, m = 3), so every other frequency
* somehow relates to this frequency.
*/
if ((freq_mhz % 6) == 2 || (freq_mhz % 6) == 4)
*m = 2;
/*
* If the frequency is a multiple of 6MHz, but the factor is
* odd, m will be 3
*/
else if ((freq_mhz / 6) & 1)
*m = 3;
/* Otherwise, we end up with m = 1 */
else
*m = 1;
/* Calculate n thanks to the above factors we already got */
*n = freq_mhz * (*m + 1) / ((*k + 1) * parent_freq_mhz) - 1;
/*
* If n end up being outbound, and that we can still decrease
* m, do it.
*/
if ((*n + 1) > 31 && (*m + 1) > 1) {
*n = (*n + 1) / 2 - 1;
*m = (*m + 1) / 2 - 1;
}
}
/**
* sunxi_get_apb1_factors() - calculates m, p factors for APB1
* sun4i_get_apb1_factors() - calculates m, p factors for APB1
* APB1 rate is calculated as follows
* rate = (parent_rate >> p) / (m + 1);
*/
static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate,
static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
u8 *n, u8 *k, u8 *m, u8 *p)
{
u8 calcm, calcp;
@ -178,7 +261,7 @@ struct factors_data {
void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
};
static struct clk_factors_config pll1_config = {
static struct clk_factors_config sun4i_pll1_config = {
.nshift = 8,
.nwidth = 5,
.kshift = 4,
@ -189,21 +272,35 @@ static struct clk_factors_config pll1_config = {
.pwidth = 2,
};
static struct clk_factors_config apb1_config = {
static struct clk_factors_config sun6i_a31_pll1_config = {
.nshift = 8,
.nwidth = 5,
.kshift = 4,
.kwidth = 2,
.mshift = 0,
.mwidth = 2,
};
static struct clk_factors_config sun4i_apb1_config = {
.mshift = 0,
.mwidth = 5,
.pshift = 16,
.pwidth = 2,
};
static const __initconst struct factors_data pll1_data = {
.table = &pll1_config,
.getter = sunxi_get_pll1_factors,
static const struct factors_data sun4i_pll1_data __initconst = {
.table = &sun4i_pll1_config,
.getter = sun4i_get_pll1_factors,
};
static const __initconst struct factors_data apb1_data = {
.table = &apb1_config,
.getter = sunxi_get_apb1_factors,
static const struct factors_data sun6i_a31_pll1_data __initconst = {
.table = &sun6i_a31_pll1_config,
.getter = sun6i_a31_get_pll1_factors,
};
static const struct factors_data sun4i_apb1_data __initconst = {
.table = &sun4i_apb1_config,
.getter = sun4i_get_apb1_factors,
};
static void __init sunxi_factors_clk_setup(struct device_node *node,
@ -221,7 +318,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
clk = clk_register_factors(NULL, clk_name, parent, 0, reg,
data->table, data->getter, &clk_lock);
if (clk) {
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, clk_name, NULL);
}
@ -239,11 +336,15 @@ struct mux_data {
u8 shift;
};
static const __initconst struct mux_data cpu_mux_data = {
static const struct mux_data sun4i_cpu_mux_data __initconst = {
.shift = 16,
};
static const __initconst struct mux_data apb1_mux_data = {
static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
.shift = 12,
};
static const struct mux_data sun4i_apb1_mux_data __initconst = {
.shift = 24,
};
@ -261,7 +362,8 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
i++;
clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg,
clk = clk_register_mux(NULL, clk_name, parents, i,
CLK_SET_RATE_NO_REPARENT, reg,
data->shift, SUNXI_MUX_GATE_WIDTH,
0, &clk_lock);
@ -277,26 +379,34 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
* sunxi_divider_clk_setup() - Setup function for simple divider clocks
*/
#define SUNXI_DIVISOR_WIDTH 2
struct div_data {
u8 shift;
u8 pow;
u8 shift;
u8 pow;
u8 width;
};
static const __initconst struct div_data axi_data = {
.shift = 0,
.pow = 0,
static const struct div_data sun4i_axi_data __initconst = {
.shift = 0,
.pow = 0,
.width = 2,
};
static const __initconst struct div_data ahb_data = {
.shift = 4,
.pow = 1,
static const struct div_data sun4i_ahb_data __initconst = {
.shift = 4,
.pow = 1,
.width = 2,
};
static const __initconst struct div_data apb0_data = {
.shift = 8,
.pow = 1,
static const struct div_data sun4i_apb0_data __initconst = {
.shift = 8,
.pow = 1,
.width = 2,
};
static const struct div_data sun6i_a31_apb2_div_data __initconst = {
.shift = 0,
.pow = 0,
.width = 4,
};
static void __init sunxi_divider_clk_setup(struct device_node *node,
@ -312,7 +422,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
clk_parent = of_clk_get_parent_name(node, 0);
clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
reg, data->shift, SUNXI_DIVISOR_WIDTH,
reg, data->shift, data->width,
data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
&clk_lock);
if (clk) {
@ -333,34 +443,70 @@ struct gates_data {
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
};
static const __initconst struct gates_data sun4i_axi_gates_data = {
static const struct gates_data sun4i_axi_gates_data __initconst = {
.mask = {1},
};
static const __initconst struct gates_data sun4i_ahb_gates_data = {
static const struct gates_data sun4i_ahb_gates_data __initconst = {
.mask = {0x7F77FFF, 0x14FB3F},
};
static const __initconst struct gates_data sun5i_a13_ahb_gates_data = {
static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
.mask = {0x147667e7, 0x185915},
};
static const struct gates_data sun5i_a13_ahb_gates_data __initconst = {
.mask = {0x107067e7, 0x185111},
};
static const __initconst struct gates_data sun4i_apb0_gates_data = {
static const struct gates_data sun6i_a31_ahb1_gates_data __initconst = {
.mask = {0xEDFE7F62, 0x794F931},
};
static const struct gates_data sun7i_a20_ahb_gates_data __initconst = {
.mask = { 0x12f77fff, 0x16ff3f },
};
static const struct gates_data sun4i_apb0_gates_data __initconst = {
.mask = {0x4EF},
};
static const __initconst struct gates_data sun5i_a13_apb0_gates_data = {
static const struct gates_data sun5i_a10s_apb0_gates_data __initconst = {
.mask = {0x469},
};
static const struct gates_data sun5i_a13_apb0_gates_data __initconst = {
.mask = {0x61},
};
static const __initconst struct gates_data sun4i_apb1_gates_data = {
static const struct gates_data sun7i_a20_apb0_gates_data __initconst = {
.mask = { 0x4ff },
};
static const struct gates_data sun4i_apb1_gates_data __initconst = {
.mask = {0xFF00F7},
};
static const __initconst struct gates_data sun5i_a13_apb1_gates_data = {
static const struct gates_data sun5i_a10s_apb1_gates_data __initconst = {
.mask = {0xf0007},
};
static const struct gates_data sun5i_a13_apb1_gates_data __initconst = {
.mask = {0xa0007},
};
static const struct gates_data sun6i_a31_apb1_gates_data __initconst = {
.mask = {0x3031},
};
static const struct gates_data sun6i_a31_apb2_gates_data __initconst = {
.mask = {0x3F000F},
};
static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
.mask = { 0xff80ff },
};
static void __init sunxi_gates_clk_setup(struct device_node *node,
struct gates_data *data)
{
@ -410,43 +556,49 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
/* Matches for of_clk_init */
static const __initconst struct of_device_id clk_match[] = {
{.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,},
{}
};
/* Matches for factors clocks */
static const __initconst struct of_device_id clk_factors_match[] = {
{.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,},
{.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,},
static const struct of_device_id clk_factors_match[] __initconst = {
{.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
{.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
{}
};
/* Matches for divider clocks */
static const __initconst struct of_device_id clk_div_match[] = {
{.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,},
{.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,},
{.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,},
static const struct of_device_id clk_div_match[] __initconst = {
{.compatible = "allwinner,sun4i-axi-clk", .data = &sun4i_axi_data,},
{.compatible = "allwinner,sun4i-ahb-clk", .data = &sun4i_ahb_data,},
{.compatible = "allwinner,sun4i-apb0-clk", .data = &sun4i_apb0_data,},
{.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
{}
};
/* Matches for mux clocks */
static const __initconst struct of_device_id clk_mux_match[] = {
{.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_mux_data,},
{.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,},
static const struct of_device_id clk_mux_match[] __initconst = {
{.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
{.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
{}
};
/* Matches for gate clocks */
static const __initconst struct of_device_id clk_gates_match[] = {
static const struct of_device_id clk_gates_match[] __initconst = {
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
{.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
{.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
{.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
{.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
{.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
{.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
{}
};
@ -467,8 +619,8 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
void __init sunxi_init_clocks(void)
{
/* Register all the simple sunxi clocks on DT */
of_clk_init(clk_match);
/* Register all the simple and basic clocks on DT */
of_clk_init(NULL);
/* Register factor clocks */
of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);

View File

@ -1566,7 +1566,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
/* audio0 */
clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0,
NULL);
clks[audio0_mux] = clk;
@ -1578,7 +1579,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
/* audio1 */
clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0,
NULL);
clks[audio1_mux] = clk;
@ -1590,7 +1592,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
/* audio2 */
clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0,
NULL);
clks[audio2_mux] = clk;
@ -1602,7 +1605,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
/* audio3 */
clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0,
NULL);
clks[audio3_mux] = clk;
@ -1614,7 +1618,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
/* audio4 */
clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0,
NULL);
clks[audio4_mux] = clk;
@ -1626,7 +1631,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
/* spdif */
clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0,
NULL);
clks[spdif_mux] = clk;
@ -1721,7 +1727,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
/* clk_out_1 */
clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
ARRAY_SIZE(clk_out1_parents), 0,
ARRAY_SIZE(clk_out1_parents),
CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
&clk_out_lock);
clks[clk_out_1_mux] = clk;
@ -1733,7 +1740,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
/* clk_out_2 */
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
ARRAY_SIZE(clk_out2_parents), 0,
ARRAY_SIZE(clk_out2_parents),
CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
&clk_out_lock);
clks[clk_out_2_mux] = clk;
@ -1745,7 +1753,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
/* clk_out_3 */
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
ARRAY_SIZE(clk_out3_parents), 0,
ARRAY_SIZE(clk_out3_parents),
CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
&clk_out_lock);
clks[clk_out_3_mux] = clk;
@ -2063,7 +2072,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base)
/* dsia */
clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
ARRAY_SIZE(mux_plld_out0_plld2_out0),
CLK_SET_RATE_NO_REPARENT,
clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
clks[dsia_mux] = clk;
clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
@ -2073,7 +2083,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base)
/* dsib */
clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
ARRAY_SIZE(mux_plld_out0_plld2_out0),
CLK_SET_RATE_NO_REPARENT,
clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
clks[dsib_mux] = clk;
clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
@ -2110,7 +2121,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base)
/* emc */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm), 0,
ARRAY_SIZE(mux_pllmcp_clkm),
CLK_SET_RATE_NO_REPARENT,
clk_base + CLK_SOURCE_EMC,
29, 3, 0, NULL);
clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base,
@ -2194,7 +2206,7 @@ static const struct of_device_id pmc_match[] __initconst = {
* dfll_soc/dfll_ref apparently must be kept enabled, otherwise I2C5
* breaks
*/
static __initdata struct tegra_clk_init_table init_table[] = {
static struct tegra_clk_init_table init_table[] __initdata = {
{uarta, pll_p, 408000000, 0},
{uartb, pll_p, 408000000, 0},
{uartc, pll_p, 408000000, 0},

View File

@ -778,7 +778,8 @@ static void __init tegra20_audio_clk_init(void)
/* audio */
clk = clk_register_mux(NULL, "audio_mux", audio_parents,
ARRAY_SIZE(audio_parents), 0,
ARRAY_SIZE(audio_parents),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "audio", "audio_mux", 0,
clk_base + AUDIO_SYNC_CLK, 4,
@ -941,7 +942,8 @@ static void __init tegra20_periph_clk_init(void)
/* emc */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm), 0,
ARRAY_SIZE(mux_pllmcp_clkm),
CLK_SET_RATE_NO_REPARENT,
clk_base + CLK_SOURCE_EMC,
30, 2, 0, NULL);
clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
@ -1223,7 +1225,7 @@ static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
#endif
};
static __initdata struct tegra_clk_init_table init_table[] = {
static struct tegra_clk_init_table init_table[] __initdata = {
{pll_p, clk_max, 216000000, 1},
{pll_p_out1, clk_max, 28800000, 1},
{pll_p_out2, clk_max, 48000000, 1},

View File

@ -971,7 +971,7 @@ static void __init tegra30_pll_init(void)
/* PLLU */
clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0,
0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON |
TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK,
TEGRA_PLL_SET_LFCON,
pll_u_freq_table,
NULL);
clk_register_clkdev(clk, "pll_u", NULL);
@ -1026,7 +1026,8 @@ static void __init tegra30_pll_init(void)
/* PLLE */
clk = clk_register_mux(NULL, "pll_e_mux", pll_e_parents,
ARRAY_SIZE(pll_e_parents), 0,
ARRAY_SIZE(pll_e_parents),
CLK_SET_RATE_NO_REPARENT,
clk_base + PLLE_AUX, 2, 1, 0, NULL);
clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base,
CLK_GET_RATE_NOCACHE, 100000000, &pll_e_params,
@ -1086,7 +1087,8 @@ static void __init tegra30_audio_clk_init(void)
/* audio0 */
clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
clk_base + AUDIO_SYNC_CLK_I2S0, 4,
@ -1096,7 +1098,8 @@ static void __init tegra30_audio_clk_init(void)
/* audio1 */
clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
clk_base + AUDIO_SYNC_CLK_I2S1, 4,
@ -1106,7 +1109,8 @@ static void __init tegra30_audio_clk_init(void)
/* audio2 */
clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
clk_base + AUDIO_SYNC_CLK_I2S2, 4,
@ -1116,7 +1120,8 @@ static void __init tegra30_audio_clk_init(void)
/* audio3 */
clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
clk_base + AUDIO_SYNC_CLK_I2S3, 4,
@ -1126,7 +1131,8 @@ static void __init tegra30_audio_clk_init(void)
/* audio4 */
clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
clk_base + AUDIO_SYNC_CLK_I2S4, 4,
@ -1136,7 +1142,8 @@ static void __init tegra30_audio_clk_init(void)
/* spdif */
clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk), 0,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL);
clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
@ -1229,7 +1236,8 @@ static void __init tegra30_pmc_clk_init(void)
/* clk_out_1 */
clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
ARRAY_SIZE(clk_out1_parents), 0,
ARRAY_SIZE(clk_out1_parents),
CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
&clk_out_lock);
clks[clk_out_1_mux] = clk;
@ -1241,7 +1249,8 @@ static void __init tegra30_pmc_clk_init(void)
/* clk_out_2 */
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
ARRAY_SIZE(clk_out2_parents), 0,
ARRAY_SIZE(clk_out2_parents),
CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
&clk_out_lock);
clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
@ -1252,7 +1261,8 @@ static void __init tegra30_pmc_clk_init(void)
/* clk_out_3 */
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
ARRAY_SIZE(clk_out3_parents), 0,
ARRAY_SIZE(clk_out3_parents),
CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
&clk_out_lock);
clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
@ -1679,7 +1689,8 @@ static void __init tegra30_periph_clk_init(void)
/* emc */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm), 0,
ARRAY_SIZE(mux_pllmcp_clkm),
CLK_SET_RATE_NO_REPARENT,
clk_base + CLK_SOURCE_EMC,
30, 2, 0, NULL);
clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
@ -1901,7 +1912,7 @@ static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
#endif
};
static __initdata struct tegra_clk_init_table init_table[] = {
static struct tegra_clk_init_table init_table[] __initdata = {
{uarta, pll_p, 408000000, 0},
{uartb, pll_p, 408000000, 0},
{uartc, pll_p, 408000000, 0},

View File

@ -37,8 +37,8 @@ static void __init vexpress_sp810_init(void __iomem *base)
snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
parents, 2, 0, base + SCCTRL,
SCCTRL_TIMERENnSEL_SHIFT(i), 1,
parents, 2, CLK_SET_RATE_NO_REPARENT,
base + SCCTRL, SCCTRL_TIMERENnSEL_SHIFT(i), 1,
0, &vexpress_sp810_lock);
if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))

View File

@ -125,8 +125,9 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
div0_name = kasprintf(GFP_KERNEL, "%s_div0", clk_name);
div1_name = kasprintf(GFP_KERNEL, "%s_div1", clk_name);
clk = clk_register_mux(NULL, mux_name, parents, 4, 0,
fclk_ctrl_reg, 4, 2, 0, fclk_lock);
clk = clk_register_mux(NULL, mux_name, parents, 4,
CLK_SET_RATE_NO_REPARENT, fclk_ctrl_reg, 4, 2, 0,
fclk_lock);
clk = clk_register_divider(NULL, div0_name, mux_name,
0, fclk_ctrl_reg, 8, 6, CLK_DIVIDER_ONE_BASED |
@ -168,8 +169,8 @@ static void __init zynq_clk_register_periph_clk(enum zynq_clk clk0,
mux_name = kasprintf(GFP_KERNEL, "%s_mux", clk_name0);
div_name = kasprintf(GFP_KERNEL, "%s_div", clk_name0);
clk = clk_register_mux(NULL, mux_name, parents, 4, 0,
clk_ctrl, 4, 2, 0, lock);
clk = clk_register_mux(NULL, mux_name, parents, 4,
CLK_SET_RATE_NO_REPARENT, clk_ctrl, 4, 2, 0, lock);
clk = clk_register_divider(NULL, div_name, mux_name, 0, clk_ctrl, 8, 6,
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, lock);
@ -236,25 +237,26 @@ static void __init zynq_clk_setup(struct device_node *np)
clk = clk_register_zynq_pll("armpll_int", "ps_clk", SLCR_ARMPLL_CTRL,
SLCR_PLL_STATUS, 0, &armpll_lock);
clks[armpll] = clk_register_mux(NULL, clk_output_name[armpll],
armpll_parents, 2, 0, SLCR_ARMPLL_CTRL, 4, 1, 0,
&armpll_lock);
armpll_parents, 2, CLK_SET_RATE_NO_REPARENT,
SLCR_ARMPLL_CTRL, 4, 1, 0, &armpll_lock);
clk = clk_register_zynq_pll("ddrpll_int", "ps_clk", SLCR_DDRPLL_CTRL,
SLCR_PLL_STATUS, 1, &ddrpll_lock);
clks[ddrpll] = clk_register_mux(NULL, clk_output_name[ddrpll],
ddrpll_parents, 2, 0, SLCR_DDRPLL_CTRL, 4, 1, 0,
&ddrpll_lock);
ddrpll_parents, 2, CLK_SET_RATE_NO_REPARENT,
SLCR_DDRPLL_CTRL, 4, 1, 0, &ddrpll_lock);
clk = clk_register_zynq_pll("iopll_int", "ps_clk", SLCR_IOPLL_CTRL,
SLCR_PLL_STATUS, 2, &iopll_lock);
clks[iopll] = clk_register_mux(NULL, clk_output_name[iopll],
iopll_parents, 2, 0, SLCR_IOPLL_CTRL, 4, 1, 0,
&iopll_lock);
iopll_parents, 2, CLK_SET_RATE_NO_REPARENT,
SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock);
/* CPU clocks */
tmp = readl(SLCR_621_TRUE) & 1;
clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, 0,
SLCR_ARM_CLK_CTRL, 4, 2, 0, &armclk_lock);
clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4,
CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0,
&armclk_lock);
clk = clk_register_divider(NULL, "cpu_div", "cpu_mux", 0,
SLCR_ARM_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO, &armclk_lock);
@ -293,8 +295,9 @@ static void __init zynq_clk_setup(struct device_node *np)
swdt_ext_clk_mux_parents[i + 1] = dummy_nm;
}
clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt],
swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT,
SLCR_SWDT_CLK_SEL, 0, 1, 0, &swdtclk_lock);
swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT, SLCR_SWDT_CLK_SEL, 0, 1, 0,
&swdtclk_lock);
/* DDR clocks */
clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0,
@ -356,8 +359,9 @@ static void __init zynq_clk_setup(struct device_node *np)
gem0_mux_parents[i + 1] = of_clk_get_parent_name(np,
idx);
}
clk = clk_register_mux(NULL, "gem0_mux", periph_parents, 4, 0,
SLCR_GEM0_CLK_CTRL, 4, 2, 0, &gem0clk_lock);
clk = clk_register_mux(NULL, "gem0_mux", periph_parents, 4,
CLK_SET_RATE_NO_REPARENT, SLCR_GEM0_CLK_CTRL, 4, 2, 0,
&gem0clk_lock);
clk = clk_register_divider(NULL, "gem0_div0", "gem0_mux", 0,
SLCR_GEM0_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO, &gem0clk_lock);
@ -366,7 +370,8 @@ static void __init zynq_clk_setup(struct device_node *np)
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
&gem0clk_lock);
clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2,
CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 6, 1, 0,
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SLCR_GEM0_CLK_CTRL, 6, 1, 0,
&gem0clk_lock);
clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0],
"gem0_emio_mux", CLK_SET_RATE_PARENT,
@ -379,8 +384,9 @@ static void __init zynq_clk_setup(struct device_node *np)
gem1_mux_parents[i + 1] = of_clk_get_parent_name(np,
idx);
}
clk = clk_register_mux(NULL, "gem1_mux", periph_parents, 4, 0,
SLCR_GEM1_CLK_CTRL, 4, 2, 0, &gem1clk_lock);
clk = clk_register_mux(NULL, "gem1_mux", periph_parents, 4,
CLK_SET_RATE_NO_REPARENT, SLCR_GEM1_CLK_CTRL, 4, 2, 0,
&gem1clk_lock);
clk = clk_register_divider(NULL, "gem1_div0", "gem1_mux", 0,
SLCR_GEM1_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO, &gem1clk_lock);
@ -389,7 +395,8 @@ static void __init zynq_clk_setup(struct device_node *np)
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
&gem1clk_lock);
clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2,
CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 6, 1, 0,
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
SLCR_GEM1_CLK_CTRL, 6, 1, 0,
&gem1clk_lock);
clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1],
"gem1_emio_mux", CLK_SET_RATE_PARENT,
@ -409,8 +416,9 @@ static void __init zynq_clk_setup(struct device_node *np)
can_mio_mux_parents[i] = dummy_nm;
}
kfree(clk_name);
clk = clk_register_mux(NULL, "can_mux", periph_parents, 4, 0,
SLCR_CAN_CLK_CTRL, 4, 2, 0, &canclk_lock);
clk = clk_register_mux(NULL, "can_mux", periph_parents, 4,
CLK_SET_RATE_NO_REPARENT, SLCR_CAN_CLK_CTRL, 4, 2, 0,
&canclk_lock);
clk = clk_register_divider(NULL, "can_div0", "can_mux", 0,
SLCR_CAN_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO, &canclk_lock);
@ -425,17 +433,21 @@ static void __init zynq_clk_setup(struct device_node *np)
CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 1, 0,
&canclk_lock);
clk = clk_register_mux(NULL, "can0_mio_mux",
can_mio_mux_parents, 54, CLK_SET_RATE_PARENT,
SLCR_CAN_MIOCLK_CTRL, 0, 6, 0, &canmioclk_lock);
can_mio_mux_parents, 54, CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 0, 6, 0,
&canmioclk_lock);
clk = clk_register_mux(NULL, "can1_mio_mux",
can_mio_mux_parents, 54, CLK_SET_RATE_PARENT,
SLCR_CAN_MIOCLK_CTRL, 16, 6, 0, &canmioclk_lock);
can_mio_mux_parents, 54, CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 16, 6,
0, &canmioclk_lock);
clks[can0] = clk_register_mux(NULL, clk_output_name[can0],
can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT,
SLCR_CAN_MIOCLK_CTRL, 6, 1, 0, &canmioclk_lock);
can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 6, 1, 0,
&canmioclk_lock);
clks[can1] = clk_register_mux(NULL, clk_output_name[can1],
can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT,
SLCR_CAN_MIOCLK_CTRL, 22, 1, 0, &canmioclk_lock);
can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT |
CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 22, 1,
0, &canmioclk_lock);
for (i = 0; i < ARRAY_SIZE(dbgtrc_emio_input_names); i++) {
int idx = of_property_match_string(np, "clock-names",
@ -444,13 +456,15 @@ static void __init zynq_clk_setup(struct device_node *np)
dbg_emio_mux_parents[i + 1] = of_clk_get_parent_name(np,
idx);
}
clk = clk_register_mux(NULL, "dbg_mux", periph_parents, 4, 0,
SLCR_DBG_CLK_CTRL, 4, 2, 0, &dbgclk_lock);
clk = clk_register_mux(NULL, "dbg_mux", periph_parents, 4,
CLK_SET_RATE_NO_REPARENT, SLCR_DBG_CLK_CTRL, 4, 2, 0,
&dbgclk_lock);
clk = clk_register_divider(NULL, "dbg_div", "dbg_mux", 0,
SLCR_DBG_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO, &dbgclk_lock);
clk = clk_register_mux(NULL, "dbg_emio_mux", dbg_emio_mux_parents, 2, 0,
SLCR_DBG_CLK_CTRL, 6, 1, 0, &dbgclk_lock);
clk = clk_register_mux(NULL, "dbg_emio_mux", dbg_emio_mux_parents, 2,
CLK_SET_RATE_NO_REPARENT, SLCR_DBG_CLK_CTRL, 6, 1, 0,
&dbgclk_lock);
clks[dbg_trc] = clk_register_gate(NULL, clk_output_name[dbg_trc],
"dbg_emio_mux", CLK_SET_RATE_PARENT, SLCR_DBG_CLK_CTRL,
0, 0, &dbgclk_lock);

View File

@ -50,6 +50,9 @@ struct zynq_pll {
#define PLLCTRL_RESET_MASK 1
#define PLLCTRL_RESET_SHIFT 0
#define PLL_FBDIV_MIN 13
#define PLL_FBDIV_MAX 66
/**
* zynq_pll_round_rate() - Round a clock frequency
* @hw: Handle between common and hardware-specific interfaces
@ -63,10 +66,10 @@ static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
u32 fbdiv;
fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
if (fbdiv < 13)
fbdiv = 13;
else if (fbdiv > 66)
fbdiv = 66;
if (fbdiv < PLL_FBDIV_MIN)
fbdiv = PLL_FBDIV_MIN;
else if (fbdiv > PLL_FBDIV_MAX)
fbdiv = PLL_FBDIV_MAX;
return *prate * fbdiv;
}
@ -182,7 +185,13 @@ static const struct clk_ops zynq_pll_ops = {
/**
* clk_register_zynq_pll() - Register PLL with the clock framework
* @np Pointer to the DT device node
* @name PLL name
* @parent Parent clock name
* @pll_ctrl Pointer to PLL control register
* @pll_status Pointer to PLL status register
* @lock_index Bit index to this PLL's lock status bit in @pll_status
* @lock Register lock
* Returns handle to the registered clock.
*/
struct clk *clk_register_zynq_pll(const char *name, const char *parent,
void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,

View File

@ -368,10 +368,6 @@ static void __init samsung_clocksource_init(void)
static void __init samsung_timer_resources(void)
{
pwm.timerclk = clk_get(NULL, "timers");
if (IS_ERR(pwm.timerclk))
panic("failed to get timers clock for timer");
clk_prepare_enable(pwm.timerclk);
pwm.tcnt_max = (1UL << pwm.variant.bits) - 1;
@ -416,6 +412,10 @@ void __init samsung_pwm_clocksource_init(void __iomem *base,
memcpy(&pwm.variant, variant, sizeof(pwm.variant));
memcpy(pwm.irq, irqs, SAMSUNG_PWM_NUM * sizeof(*irqs));
pwm.timerclk = clk_get(NULL, "timers");
if (IS_ERR(pwm.timerclk))
panic("failed to get timers clock for timer");
_samsung_pwm_clocksource_init();
}
@ -447,6 +447,10 @@ static void __init samsung_pwm_alloc(struct device_node *np,
return;
}
pwm.timerclk = of_clk_get_by_name(np, "timers");
if (IS_ERR(pwm.timerclk))
panic("failed to get timers clock for timer");
_samsung_pwm_clocksource_init();
}

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Device Tree binding constants for Samsung S3C64xx clock controller.
*/
#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H
/*
* Let each exported clock get a unique index, which is used on DT-enabled
* platforms to lookup the clock from a clock specifier. These indices are
* therefore considered an ABI and so must not be changed. This implies
* that new clocks should be added either in free spaces between clock groups
* or at the end.
*/
/* Core clocks. */
#define CLK27M 1
#define CLK48M 2
#define FOUT_APLL 3
#define FOUT_MPLL 4
#define FOUT_EPLL 5
#define ARMCLK 6
#define HCLKX2 7
#define HCLK 8
#define PCLK 9
/* HCLK bus clocks. */
#define HCLK_3DSE 16
#define HCLK_UHOST 17
#define HCLK_SECUR 18
#define HCLK_SDMA1 19
#define HCLK_SDMA0 20
#define HCLK_IROM 21
#define HCLK_DDR1 22
#define HCLK_MEM1 23
#define HCLK_MEM0 24
#define HCLK_USB 25
#define HCLK_HSMMC2 26
#define HCLK_HSMMC1 27
#define HCLK_HSMMC0 28
#define HCLK_MDP 29
#define HCLK_DHOST 30
#define HCLK_IHOST 31
#define HCLK_DMA1 32
#define HCLK_DMA0 33
#define HCLK_JPEG 34
#define HCLK_CAMIF 35
#define HCLK_SCALER 36
#define HCLK_2D 37
#define HCLK_TV 38
#define HCLK_POST0 39
#define HCLK_ROT 40
#define HCLK_LCD 41
#define HCLK_TZIC 42
#define HCLK_INTC 43
#define HCLK_MFC 44
#define HCLK_DDR0 45
/* PCLK bus clocks. */
#define PCLK_IIC1 48
#define PCLK_IIS2 49
#define PCLK_SKEY 50
#define PCLK_CHIPID 51
#define PCLK_SPI1 52
#define PCLK_SPI0 53
#define PCLK_HSIRX 54
#define PCLK_HSITX 55
#define PCLK_GPIO 56
#define PCLK_IIC0 57
#define PCLK_IIS1 58
#define PCLK_IIS0 59
#define PCLK_AC97 60
#define PCLK_TZPC 61
#define PCLK_TSADC 62
#define PCLK_KEYPAD 63
#define PCLK_IRDA 64
#define PCLK_PCM1 65
#define PCLK_PCM0 66
#define PCLK_PWM 67
#define PCLK_RTC 68
#define PCLK_WDT 69
#define PCLK_UART3 70
#define PCLK_UART2 71
#define PCLK_UART1 72
#define PCLK_UART0 73
#define PCLK_MFC 74
/* Special clocks. */
#define SCLK_UHOST 80
#define SCLK_MMC2_48 81
#define SCLK_MMC1_48 82
#define SCLK_MMC0_48 83
#define SCLK_MMC2 84
#define SCLK_MMC1 85
#define SCLK_MMC0 86
#define SCLK_SPI1_48 87
#define SCLK_SPI0_48 88
#define SCLK_SPI1 89
#define SCLK_SPI0 90
#define SCLK_DAC27 91
#define SCLK_TV27 92
#define SCLK_SCALER27 93
#define SCLK_SCALER 94
#define SCLK_LCD27 95
#define SCLK_LCD 96
#define SCLK_FIMC 97
#define SCLK_POST0_27 98
#define SCLK_AUDIO2 99
#define SCLK_POST0 100
#define SCLK_AUDIO1 101
#define SCLK_AUDIO0 102
#define SCLK_SECUR 103
#define SCLK_IRDA 104
#define SCLK_UART 105
#define SCLK_MFC 106
#define SCLK_CAM 107
#define SCLK_JPEG 108
#define SCLK_ONENAND 109
/* MEM0 bus clocks - S3C6410-specific. */
#define MEM0_CFCON 112
#define MEM0_ONENAND1 113
#define MEM0_ONENAND0 114
#define MEM0_NFCON 115
#define MEM0_SROM 116
/* Muxes. */
#define MOUT_APLL 128
#define MOUT_MPLL 129
#define MOUT_EPLL 130
#define MOUT_MFC 131
#define MOUT_AUDIO0 132
#define MOUT_AUDIO1 133
#define MOUT_UART 134
#define MOUT_SPI0 135
#define MOUT_SPI1 136
#define MOUT_MMC0 137
#define MOUT_MMC1 138
#define MOUT_MMC2 139
#define MOUT_UHOST 140
#define MOUT_IRDA 141
#define MOUT_LCD 142
#define MOUT_SCALER 143
#define MOUT_DAC27 144
#define MOUT_TV27 145
#define MOUT_AUDIO2 146
/* Dividers. */
#define DOUT_MPLL 160
#define DOUT_SECUR 161
#define DOUT_CAM 162
#define DOUT_JPEG 163
#define DOUT_MFC 164
#define DOUT_MMC0 165
#define DOUT_MMC1 166
#define DOUT_MMC2 167
#define DOUT_LCD 168
#define DOUT_SCALER 169
#define DOUT_UHOST 170
#define DOUT_SPI0 171
#define DOUT_SPI1 172
#define DOUT_AUDIO0 173
#define DOUT_AUDIO1 174
#define DOUT_UART 175
#define DOUT_IRDA 176
#define DOUT_FIMC 177
#define DOUT_AUDIO2 178
/* Total number of clocks. */
#define NR_CLKS (DOUT_AUDIO2 + 1)
#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C64XX_CLOCK_H */

View File

@ -33,8 +33,11 @@ struct clk {
const char **parent_names;
struct clk **parents;
u8 num_parents;
u8 new_parent_index;
unsigned long rate;
unsigned long new_rate;
struct clk *new_parent;
struct clk *new_child;
unsigned long flags;
unsigned int enable_count;
unsigned int prepare_count;

View File

@ -12,6 +12,7 @@
#define __LINUX_CLK_PROVIDER_H
#include <linux/clk.h>
#include <linux/io.h>
#ifdef CONFIG_COMMON_CLK
@ -27,6 +28,7 @@
#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */
#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
struct clk_hw;
@ -79,6 +81,10 @@ struct clk_hw;
* @round_rate: Given a target rate as input, returns the closest rate actually
* supported by the clock.
*
* @determine_rate: Given a target rate as input, returns the closest rate
* actually supported by the clock, and optionally the parent clock
* that should be used to provide the clock rate.
*
* @get_parent: Queries the hardware to determine the parent of a clock. The
* return value is a u8 which specifies the index corresponding to
* the parent clock. This index can be applied to either the
@ -126,6 +132,9 @@ struct clk_ops {
unsigned long parent_rate);
long (*round_rate)(struct clk_hw *hw, unsigned long,
unsigned long *);
long (*determine_rate)(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw, unsigned long,
@ -327,8 +336,10 @@ struct clk_mux {
#define CLK_MUX_INDEX_ONE BIT(0)
#define CLK_MUX_INDEX_BIT BIT(1)
#define CLK_MUX_HIWORD_MASK BIT(2)
#define CLK_MUX_READ_ONLY BIT(3) /* mux setting cannot be changed */
extern const struct clk_ops clk_mux_ops;
extern const struct clk_ops clk_mux_ro_ops;
struct clk *clk_register_mux(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
@ -418,6 +429,7 @@ const char *__clk_get_name(struct clk *clk);
struct clk_hw *__clk_get_hw(struct clk *clk);
u8 __clk_get_num_parents(struct clk *clk);
struct clk *__clk_get_parent(struct clk *clk);
struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
unsigned int __clk_get_enable_count(struct clk *clk);
unsigned int __clk_get_prepare_count(struct clk *clk);
unsigned long __clk_get_rate(struct clk *clk);
@ -425,6 +437,9 @@ unsigned long __clk_get_flags(struct clk *clk);
bool __clk_is_prepared(struct clk *clk);
bool __clk_is_enabled(struct clk *clk);
struct clk *__clk_lookup(const char *name);
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p);
/*
* FIXME clock api without lock protection
@ -490,5 +505,21 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
#define of_clk_init(matches) \
{ while (0); }
#endif /* CONFIG_OF */
/*
* wrap access to peripherals in accessor routines
* for improved portability across platforms
*/
static inline u32 clk_readl(u32 __iomem *reg)
{
return readl(reg);
}
static inline void clk_writel(u32 val, u32 __iomem *reg)
{
writel(val, reg);
}
#endif /* CONFIG_COMMON_CLK */
#endif /* CLK_PROVIDER_H */