diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl
index 2428cc04dbc84b..f3abca7ec53d62 100644
--- a/Documentation/DocBook/kgdb.tmpl
+++ b/Documentation/DocBook/kgdb.tmpl
@@ -197,6 +197,7 @@
may be configured as a kernel built-in or a kernel loadable module.
You can only make use of kgdbwait and early
debugging if you build kgdboc into the kernel as a built-in.
+
Optionally you can elect to activate kms (Kernel Mode
Setting) integration. When you use kms with kgdboc and you have a
video driver that has atomic mode setting hooks, it is possible to
@@ -206,7 +207,6 @@
crashes or doing analysis of memory with kdb while allowing the
full graphics console applications to run.
-
kgdboc arguments
Usage: kgdboc=[kms][[,]kbd][[,]serial_device][,baud]
@@ -284,7 +284,6 @@
-
NOTE: Kgdboc does not support interrupting the target via the
gdb remote protocol. You must manually send a sysrq-g unless you
have a proxy that splits console output to a terminal program.
@@ -305,6 +304,7 @@
as well as on the initial connect, or to use a debugger proxy that
allows an unmodified gdb to do the debugging.
+
@@ -350,12 +350,12 @@
+
IMPORTANT NOTE: You cannot use kgdboc + kgdbcon on a tty that is an
active system console. An example of incorrect usage is console=ttyS0,115200 kgdboc=ttyS0 kgdbcon
It is possible to use this option with kgdboc on a tty that is not a system console.
-
Run time parameter: kgdbreboot
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 4ff84623d5e16e..0e4f90aa1c136e 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -73,6 +73,8 @@ the operations defined in clk.h:
unsigned long *parent_rate);
long (*determine_rate)(struct clk_hw *hw,
unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk);
int (*set_parent)(struct clk_hw *hw, u8 index);
diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt
index c81839b52c4dd0..ad697781f9ac47 100644
--- a/Documentation/device-mapper/dm-crypt.txt
+++ b/Documentation/device-mapper/dm-crypt.txt
@@ -51,7 +51,7 @@ Parameters: \
Otherwise #opt_params is the number of following arguments.
Example of optional parameters section:
- 1 allow_discards
+ 3 allow_discards same_cpu_crypt submit_from_crypt_cpus
allow_discards
Block discard requests (a.k.a. TRIM) are passed through the crypt device.
@@ -63,6 +63,19 @@ allow_discards
used space etc.) if the discarded blocks can be located easily on the
device later.
+same_cpu_crypt
+ Perform encryption using the same cpu that IO was submitted on.
+ The default is to use an unbound workqueue so that encryption work
+ is automatically balanced between available CPUs.
+
+submit_from_crypt_cpus
+ Disable offloading writes to a separate thread after encryption.
+ There are some situations where offloading write bios from the
+ encryption threads to a single thread degrades performance
+ significantly. The default is to offload write bios to the same
+ thread because it benefits CFQ to have writes submitted using the
+ same context.
+
Example scripts
===============
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
diff --git a/Documentation/devicetree/bindings/clock/exynos7-clock.txt b/Documentation/devicetree/bindings/clock/exynos7-clock.txt
index 6d3d5f80c1c318..6bf1e7493f61fe 100644
--- a/Documentation/devicetree/bindings/clock/exynos7-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos7-clock.txt
@@ -34,6 +34,8 @@ Required Properties for Clock Controller:
- "samsung,exynos7-clock-peris"
- "samsung,exynos7-clock-fsys0"
- "samsung,exynos7-clock-fsys1"
+ - "samsung,exynos7-clock-mscl"
+ - "samsung,exynos7-clock-aud"
- reg: physical base address of the controller and the length of
memory mapped region.
@@ -53,6 +55,7 @@ Input clocks for top0 clock controller:
- dout_sclk_bus1_pll
- dout_sclk_cc_pll
- dout_sclk_mfc_pll
+ - dout_sclk_aud_pll
Input clocks for top1 clock controller:
- fin_pll
@@ -76,6 +79,14 @@ Input clocks for peric1 clock controller:
- sclk_uart1
- sclk_uart2
- sclk_uart3
+ - sclk_spi0
+ - sclk_spi1
+ - sclk_spi2
+ - sclk_spi3
+ - sclk_spi4
+ - sclk_i2s1
+ - sclk_pcm1
+ - sclk_spdif
Input clocks for peris clock controller:
- fin_pll
@@ -91,3 +102,7 @@ Input clocks for fsys1 clock controller:
- dout_aclk_fsys1_200
- dout_sclk_mmc0
- dout_sclk_mmc1
+
+Input clocks for aud clock controller:
+ - fin_pll
+ - fout_aud_pll
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
index ded5d6212c84df..c6620bc9670364 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
@@ -1,4 +1,4 @@
-NVIDIA Tegra124 Clock And Reset Controller
+NVIDIA Tegra124 and Tegra132 Clock And Reset Controller
This binding uses the common clock binding:
Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -7,14 +7,16 @@ The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
for muxing and gating Tegra's clocks, and setting their rates.
Required properties :
-- compatible : Should be "nvidia,tegra124-car"
+- compatible : Should be "nvidia,tegra124-car" or "nvidia,tegra132-car"
- reg : Should contain CAR registers location and length
- clocks : Should contain phandle and clock specifiers for two clocks:
the 32 KHz "32k_in", and the board-specific oscillator "osc".
- #clock-cells : Should be 1.
In clock consumers, this cell represents the clock ID exposed by the
- CAR. The assignments may be found in header file
- .
+ CAR. The assignments may be found in the header files
+ (which covers IDs common
+ to Tegra124 and Tegra132) and
+ (for Tegra124-specific clocks).
- #reset-cells : Should be 1.
In clock consumers, this cell represents the bit number in the CAR's
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
diff --git a/Documentation/devicetree/bindings/clock/qcom,lcc.txt b/Documentation/devicetree/bindings/clock/qcom,lcc.txt
new file mode 100644
index 00000000000000..dd755be63a011c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,lcc.txt
@@ -0,0 +1,21 @@
+Qualcomm LPASS Clock & Reset Controller Binding
+------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+ "qcom,lcc-msm8960"
+ "qcom,lcc-apq8064"
+ "qcom,lcc-ipq8064"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+- #reset-cells : shall contain 1
+
+Example:
+ clock-controller@28000000 {
+ compatible = "qcom,lcc-ipq8064";
+ reg = <0x28000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
index 266ff9d232293a..df4a259a6898c5 100644
--- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
+++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
@@ -1,6 +1,6 @@
-* Clock Block on Freescale CoreNet Platforms
+* Clock Block on Freescale QorIQ Platforms
-Freescale CoreNet chips take primary clocking input from the external
+Freescale qoriq chips take primary clocking input from the external
SYSCLK signal. The SYSCLK input (frequency) is multiplied using
multiple phase locked loops (PLL) to create a variety of frequencies
which can then be passed to a variety of internal logic, including
@@ -29,6 +29,7 @@ Required properties:
* "fsl,t4240-clockgen"
* "fsl,b4420-clockgen"
* "fsl,b4860-clockgen"
+ * "fsl,ls1021a-clockgen"
Chassis clock strings include:
* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
index 2e18676bd4b565..0a80fa70ca265c 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -11,6 +11,7 @@ Required Properties:
- compatible: Must be one of the following
- "renesas,r7s72100-mstp-clocks" for R7S72100 (RZ) MSTP gate clocks
+ - "renesas,r8a73a4-mstp-clocks" for R8A73A4 (R-Mobile APE6) MSTP gate clocks
- "renesas,r8a7740-mstp-clocks" for R8A7740 (R-Mobile A1) MSTP gate clocks
- "renesas,r8a7779-mstp-clocks" for R8A7779 (R-Car H1) MSTP gate clocks
- "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks
diff --git a/Documentation/devicetree/bindings/clock/renesas,r8a73a4-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,r8a73a4-cpg-clocks.txt
new file mode 100644
index 00000000000000..ece92393e80d46
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/renesas,r8a73a4-cpg-clocks.txt
@@ -0,0 +1,33 @@
+* Renesas R8A73A4 Clock Pulse Generator (CPG)
+
+The CPG generates core clocks for the R8A73A4 SoC. It includes five PLLs
+and several fixed ratio dividers.
+
+Required Properties:
+
+ - compatible: Must be "renesas,r8a73a4-cpg-clocks"
+
+ - reg: Base address and length of the memory resource used by the CPG
+
+ - clocks: Reference to the parent clocks ("extal1" and "extal2")
+
+ - #clock-cells: Must be 1
+
+ - clock-output-names: The names of the clocks. Supported clocks are "main",
+ "pll0", "pll1", "pll2", "pll2s", "pll2h", "z", "z2", "i", "m3", "b",
+ "m1", "m2", "zx", "zs", and "hp".
+
+
+Example
+-------
+
+ cpg_clocks: cpg_clocks@e6150000 {
+ compatible = "renesas,r8a73a4-cpg-clocks";
+ reg = <0 0xe6150000 0 0x10000>;
+ clocks = <&extal1_clk>, <&extal2_clk>;
+ #clock-cells = <1>;
+ clock-output-names = "main", "pll0", "pll1", "pll2",
+ "pll2s", "pll2h", "z", "z2",
+ "i", "m3", "b", "m1", "m2",
+ "zx", "zs", "hp";
+ };
diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
index e6ad35b894f919..b02944fba9de4f 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
@@ -8,15 +8,18 @@ Required Properties:
- compatible: Must be one of
- "renesas,r8a7790-cpg-clocks" for the r8a7790 CPG
- "renesas,r8a7791-cpg-clocks" for the r8a7791 CPG
+ - "renesas,r8a7793-cpg-clocks" for the r8a7793 CPG
- "renesas,r8a7794-cpg-clocks" for the r8a7794 CPG
- "renesas,rcar-gen2-cpg-clocks" for the generic R-Car Gen2 CPG
- reg: Base address and length of the memory resource used by the CPG
- - clocks: Reference to the parent clock
+ - clocks: References to the parent clocks: first to the EXTAL clock, second
+ to the USB_EXTAL clock
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "main",
- "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1" and "z"
+ "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1", "z", "rcan", and
+ "adsp"
Example
@@ -26,8 +29,9 @@ Example
compatible = "renesas,r8a7790-cpg-clocks",
"renesas,rcar-gen2-cpg-clocks";
reg = <0 0xe6150000 0 0x1000>;
- clocks = <&extal_clk>;
+ clocks = <&extal_clk &usb_extal_clk>;
#clock-cells = <1>;
clock-output-names = "main", "pll0, "pll1", "pll3",
- "lb", "qspi", "sdh", "sd0", "sd1", "z";
+ "lb", "qspi", "sdh", "sd0", "sd1", "z",
+ "rcan", "adsp";
};
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 67b2b99f2b339f..60b44285250d3b 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -26,7 +26,7 @@ Required properties:
"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-ar100-clk" - for the AR100 on A31
- "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
+ "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
"allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
@@ -55,9 +55,11 @@ Required properties:
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
- "allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10
- "allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10
+ "allwinner,sun4i-a10-mmc-clk" - for the MMC clock
+ "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
+ "allwinner,sun9i-a80-mmc-config-clk" - for mmc gates + resets on A80
"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
+ "allwinner,sun9i-a80-mod0-clk" - for module 0 (storage) clocks on A80
"allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23
"allwinner,sun7i-a20-out-clk" - for the external output clocks
"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
@@ -73,7 +75,9 @@ Required properties for all clocks:
- #clock-cells : from common clock binding; shall be set to 0 except for
the following compatibles where it shall be set to 1:
"allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk",
- "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk"
+ "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk",
+ "allwinner,*-usb-clk", "allwinner,*-mmc-clk",
+ "allwinner,*-mmc-config-clk"
- clock-output-names : shall be the corresponding names of the outputs.
If the clock module only has one output, the name shall be the
module name.
@@ -81,6 +85,10 @@ Required properties for all clocks:
And "allwinner,*-usb-clk" clocks also require:
- reset-cells : shall be set to 1
+The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
+- #reset-cells : shall be set to 1
+- resets : shall be the reset control phandle for the mmc block.
+
For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
dummy clocks at 25 MHz and 125 MHz, respectively. See example.
@@ -95,6 +103,14 @@ For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output
is the normal PLL6 output, or "pll6". The second output is rate doubled
PLL6, or "pll6x2".
+The "allwinner,*-mmc-clk" clocks have three different outputs: the
+main clock, with the ID 0, and the output and sample clocks, with the
+IDs 1 and 2, respectively.
+
+The "allwinner,sun9i-a80-mmc-config-clk" clock has one clock/reset output
+per mmc controller. The number of outputs is determined by the size of
+the address block, which is related to the overall mmc block.
+
For example:
osc24M: clk@01c20050 {
@@ -138,11 +154,11 @@ cpu: cpu@01c20054 {
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc0";
+ clock-output-names = "mmc0", "mmc0_output", "mmc0_sample";
};
mii_phy_tx_clk: clk@2 {
@@ -170,3 +186,16 @@ gmac_clk: clk@01c20164 {
clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
clock-output-names = "gmac";
};
+
+mmc_config_clk: clk@01c13000 {
+ compatible = "allwinner,sun9i-a80-mmc-config-clk";
+ reg = <0x01c13000 0x10>;
+ clocks = <&ahb0_gates 8>;
+ clock-names = "ahb";
+ resets = <&ahb0_resets 8>;
+ reset-names = "ahb";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ clock-output-names = "mmc0_config", "mmc1_config",
+ "mmc2_config", "mmc3_config";
+};
diff --git a/Documentation/devicetree/bindings/clock/ti,cdce706.txt b/Documentation/devicetree/bindings/clock/ti,cdce706.txt
new file mode 100644
index 00000000000000..616836e7e1e256
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,cdce706.txt
@@ -0,0 +1,42 @@
+Bindings for Texas Instruments CDCE706 programmable 3-PLL clock
+synthesizer/multiplier/divider.
+
+Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf
+
+I2C device node required properties:
+- compatible: shall be "ti,cdce706".
+- reg: i2c device address, shall be in range [0x68...0x6b].
+- #clock-cells: from common clock binding; shall be set to 1.
+- clocks: from common clock binding; list of parent clock
+ handles, shall be reference clock(s) connected to CLK_IN0
+ and CLK_IN1 pins.
+- clock-names: shall be clk_in0 and/or clk_in1. Use clk_in0
+ in case of crystal oscillator or differential signal input
+ configuration. Use clk_in0 and clk_in1 in case of independent
+ single-ended LVCMOS inputs configuration.
+
+Example:
+
+ clocks {
+ clk54: clk54 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <54000000>;
+ };
+ };
+ ...
+ i2c0: i2c-master@0d090000 {
+ ...
+ cdce706: clock-synth@69 {
+ compatible = "ti,cdce706";
+ #clock-cells = <1>;
+ reg = <0x69>;
+ clocks = <&clk54>;
+ clock-names = "clk_in0";
+ };
+ };
+ ...
+ simple-audio-card,codec {
+ ...
+ clocks = <&cdce706 4>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti/fapll.txt b/Documentation/devicetree/bindings/clock/ti/fapll.txt
new file mode 100644
index 00000000000000..c19b3f253b8cf7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti/fapll.txt
@@ -0,0 +1,33 @@
+Binding for Texas Instruments FAPLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped FAPLL with usually two selectable input clocks
+(reference clock and bypass clock), and one or more child
+syntesizers.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,dm816-fapll-clock"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
+- reg : address and length of the register set for controlling the FAPLL.
+
+Examples:
+ main_fapll: main_fapll {
+ #clock-cells = <1>;
+ compatible = "ti,dm816-fapll-clock";
+ reg = <0x400 0x40>;
+ clocks = <&sys_clkin_ck &sys_clkin_ck>;
+ clock-indices = <1>, <2>, <3>, <4>, <5>,
+ <6>, <7>;
+ clock-output-names = "main_pll_clk1",
+ "main_pll_clk2",
+ "main_pll_clk3",
+ "main_pll_clk4",
+ "main_pll_clk5",
+ "main_pll_clk6",
+ "main_pll_clk7";
+ };
diff --git a/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt b/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt
new file mode 100644
index 00000000000000..81f982ccca3155
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/brcm,iproc-i2c.txt
@@ -0,0 +1,37 @@
+Broadcom iProc I2C controller
+
+Required properties:
+
+- compatible:
+ Must be "brcm,iproc-i2c"
+
+- reg:
+ Define the base and range of the I/O address space that contain the iProc
+ I2C controller registers
+
+- interrupts:
+ Should contain the I2C interrupt
+
+- clock-frequency:
+ This is the I2C bus clock. Need to be either 100000 or 400000
+
+- #address-cells:
+ Always 1 (for I2C addresses)
+
+- #size-cells:
+ Always 0
+
+Example:
+ i2c0: i2c@18008000 {
+ compatible = "brcm,iproc-i2c";
+ reg = <0x18008000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = ;
+ clock-frequency = <100000>;
+
+ codec: wm8750@1a {
+ compatible = "wlf,wm8750";
+ reg = <0x1a>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
index 34a3fb6f8488b2..cf53d5fba20a09 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt
@@ -16,6 +16,9 @@ Required Properties:
Optional Properties:
- reset-gpios: Reference to the GPIO connected to the reset input.
+ - i2c-mux-idle-disconnect: Boolean; if defined, forces mux to disconnect all
+ children in idle state. This is necessary for example, if there are several
+ multiplexers on the bus and the devices behind them use same I2C addresses.
Example:
diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
index 1637c298a1b337..17bef9a34e5075 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
@@ -4,24 +4,60 @@ Required properties:
- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst"
- reg : bus address start and address range size of device
- interrupts : interrupt number
-- clock-frequency : frequency of bus clock in Hz
+- clocks : handle to the controller clock; see the note below.
+ Mutually exclusive with opencores,ip-clock-frequency
+- opencores,ip-clock-frequency: frequency of the controller clock in Hz;
+ see the note below. Mutually exclusive with clocks
- #address-cells : should be <1>
- #size-cells : should be <0>
Optional properties:
+- clock-frequency : frequency of bus clock in Hz; see the note below.
+ Defaults to 100 KHz when the property is not specified
- reg-shift : device register offsets are shifted by this value
- reg-io-width : io register width in bytes (1, 2 or 4)
- regstep : deprecated, use reg-shift above
-Example:
+Note
+clock-frequency property is meant to control the bus frequency for i2c bus
+drivers, but it was incorrectly used to specify i2c controller input clock
+frequency. So the following rules are set to fix this situation:
+- if clock-frequency is present and neither opencores,ip-clock-frequency nor
+ clocks are, then clock-frequency specifies i2c controller clock frequency.
+ This is to keep backwards compatibility with setups using old DTB. i2c bus
+ frequency is fixed at 100 KHz.
+- if clocks is present it specifies i2c controller clock. clock-frequency
+ property specifies i2c bus frequency.
+- if opencores,ip-clock-frequency is present it specifies i2c controller
+ clock frequency. clock-frequency property specifies i2c bus frequency.
+Examples:
+
+ i2c0: ocores@a0000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "opencores,i2c-ocores";
+ reg = <0xa0000000 0x8>;
+ interrupts = <10>;
+ opencores,ip-clock-frequency = <20000000>;
+
+ reg-shift = <0>; /* 8 bit registers */
+ reg-io-width = <1>; /* 8 bit read/write */
+
+ dummy@60 {
+ compatible = "dummy";
+ reg = <0x60>;
+ };
+ };
+or
i2c0: ocores@a0000000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "opencores,i2c-ocores";
reg = <0xa0000000 0x8>;
interrupts = <10>;
- clock-frequency = <20000000>;
+ clocks = <&osc>;
+ clock-frequency = <400000>; /* i2c bus frequency 400 KHz */
reg-shift = <0>; /* 8 bit registers */
reg-io-width = <1>; /* 8 bit read/write */
diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
index dde6c22ce91a13..f0d71bc52e64be 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
@@ -21,6 +21,17 @@ Required on RK3066, RK3188 :
Optional properties :
- clock-frequency : SCL frequency to use (in Hz). If omitted, 100kHz is used.
+ - i2c-scl-rising-time-ns : Number of nanoseconds the SCL signal takes to rise
+ (t(r) in I2C specification). If not specified this is assumed to be
+ the maximum the specification allows(1000 ns for Standard-mode,
+ 300 ns for Fast-mode) which might cause slightly slower communication.
+ - i2c-scl-falling-time-ns : Number of nanoseconds the SCL signal takes to fall
+ (t(f) in the I2C specification). If not specified this is assumed to
+ be the maximum the specification allows (300 ns) which might cause
+ slightly slower communication.
+ - i2c-sda-falling-time-ns : Number of nanoseconds the SDA signal takes to fall
+ (t(f) in the I2C specification). If not specified we'll use the SCL
+ value since they are the same in nearly all cases.
Example:
@@ -39,4 +50,7 @@ i2c0: i2c@2002d000 {
clock-names = "i2c";
clocks = <&cru PCLK_I2C0>;
+
+ i2c-scl-rising-time-ns = <800>;
+ i2c-scl-falling-time-ns = <100>;
};
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 4dcd88d5f7ca45..aaa8325004d23a 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -61,9 +61,8 @@ fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
infineon,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz)
infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz)
-isl,isl12057 Intersil ISL12057 I2C RTC Chip
-isil,isl29028 (deprecated, use isl)
-isl,isl29028 Intersil ISL29028 Ambient Light and Proximity Sensor
+isil,isl12057 Intersil ISL12057 I2C RTC Chip
+isil,isl29028 Intersil ISL29028 Ambient Light and Proximity Sensor
maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
index 91b3a34671508b..4bf41d8338046e 100644
--- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
@@ -10,8 +10,8 @@ Absolute maximum transfer rate is 200MB/s
Required properties:
- compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc"
- reg : mmc controller base registers
- - clocks : a list with 2 phandle + clock specifier pairs
- - clock-names : must contain "ahb" and "mmc"
+ - clocks : a list with 4 phandle + clock specifier pairs
+ - clock-names : must contain "ahb", "mmc", "output" and "sample"
- interrupts : mmc controller interrupt
Optional properties:
@@ -25,8 +25,8 @@ Examples:
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mod";
+ clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>;
+ clock-names = "ahb", "mod", "output", "sample";
interrupts = <0 32 4>;
status = "disabled";
};
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
index 4556a3eb87c454..4aae8ed15873d1 100644
--- a/Documentation/i2c/functionality
+++ b/Documentation/i2c/functionality
@@ -12,7 +12,7 @@ FUNCTIONALITY CONSTANTS
-----------------------
For the most up-to-date list of functionality constants, please check
-!
+!
I2C_FUNC_I2C Plain i2c-level commands (Pure SMBus
adapters typically can not do these)
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt
index 90bca6f988e115..a63e5e013a8cdd 100644
--- a/Documentation/input/alps.txt
+++ b/Documentation/input/alps.txt
@@ -3,8 +3,8 @@ ALPS Touchpad Protocol
Introduction
------------
-Currently the ALPS touchpad driver supports five protocol versions in use by
-ALPS touchpads, called versions 1, 2, 3, 4 and 5.
+Currently the ALPS touchpad driver supports seven protocol versions in use by
+ALPS touchpads, called versions 1, 2, 3, 4, 5, 6 and 7.
Since roughly mid-2010 several new ALPS touchpads have been released and
integrated into a variety of laptops and netbooks. These new touchpads
@@ -240,3 +240,67 @@ For mt, the format is:
byte 3: 0 x23 x22 x21 x20 x19 x18 x17
byte 4: 0 x9 x8 x7 x6 x5 x4 x3
byte 5: 0 x16 x15 x14 x13 x12 x11 x10
+
+ALPS Absolute Mode - Protocol Version 6
+---------------------------------------
+
+For trackstick packet, the format is:
+
+ byte 0: 1 1 1 1 1 1 1 1
+ byte 1: 0 X6 X5 X4 X3 X2 X1 X0
+ byte 2: 0 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ byte 3: ? Y7 X7 ? ? M R L
+ byte 4: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
+ byte 5: 0 1 1 1 1 1 1 1
+
+For touchpad packet, the format is:
+
+ byte 0: 1 1 1 1 1 1 1 1
+ byte 1: 0 0 0 0 x3 x2 x1 x0
+ byte 2: 0 0 0 0 y3 y2 y1 y0
+ byte 3: ? x7 x6 x5 x4 ? r l
+ byte 4: ? y7 y6 y5 y4 ? ? ?
+ byte 5: z7 z6 z5 z4 z3 z2 z1 z0
+
+(v6 touchpad does not have middle button)
+
+ALPS Absolute Mode - Protocol Version 7
+---------------------------------------
+
+For trackstick packet, the format is:
+
+ byte 0: 0 1 0 0 1 0 0 0
+ byte 1: 1 1 * * 1 M R L
+ byte 2: X7 1 X5 X4 X3 X2 X1 X0
+ byte 3: Z6 1 Y6 X6 1 Y2 Y1 Y0
+ byte 4: Y7 0 Y5 Y4 Y3 1 1 0
+ byte 5: T&P 0 Z5 Z4 Z3 Z2 Z1 Z0
+
+For touchpad packet, the format is:
+
+ packet-fmt b7 b6 b5 b4 b3 b2 b1 b0
+ byte 0: TWO & MULTI L 1 R M 1 Y0-2 Y0-1 Y0-0
+ byte 0: NEW L 1 X1-5 1 1 Y0-2 Y0-1 Y0-0
+ byte 1: Y0-10 Y0-9 Y0-8 Y0-7 Y0-6 Y0-5 Y0-4 Y0-3
+ byte 2: X0-11 1 X0-10 X0-9 X0-8 X0-7 X0-6 X0-5
+ byte 3: X1-11 1 X0-4 X0-3 1 X0-2 X0-1 X0-0
+ byte 4: TWO X1-10 TWO X1-9 X1-8 X1-7 X1-6 X1-5 X1-4
+ byte 4: MULTI X1-10 TWO X1-9 X1-8 X1-7 X1-6 Y1-5 1
+ byte 4: NEW X1-10 TWO X1-9 X1-8 X1-7 X1-6 0 0
+ byte 5: TWO & NEW Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 Y1-5 Y1-4
+ byte 5: MULTI Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 F-1 F-0
+
+ L: Left button
+ R / M: Non-clickpads: Right / Middle button
+ Clickpads: When > 2 fingers are down, and some fingers
+ are in the button area, then the 2 coordinates reported
+ are for fingers outside the button area and these report
+ extra fingers being present in the right / left button
+ area. Note these fingers are not added to the F field!
+ so if a TWO packet is received and R = 1 then there are
+ 3 fingers down, etc.
+ TWO: 1: Two touches present, byte 0/4/5 are in TWO fmt
+ 0: If byte 4 bit 0 is 1, then byte 0/4/5 are in MULTI fmt
+ otherwise byte 0 bit 4 must be set and byte 0/4/5 are
+ in NEW fmt
+ F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ...
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
index 199f453cb4de10..82fbdbc1e0b062 100644
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -3,7 +3,7 @@ protocol of kernel. These should be filled by bootloader or 16-bit
real-mode setup code of the kernel. References/settings to it mainly
are in:
- arch/x86/include/asm/bootparam.h
+ arch/x86/include/uapi/asm/bootparam.h
Offset Proto Name Meaning
diff --git a/MAINTAINERS b/MAINTAINERS
index 7cfcee4e2bea2f..63d83bd6931f22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8567,7 +8567,7 @@ S: Maintained
F: drivers/scsi/sr*
SCSI RDMA PROTOCOL (SRP) INITIATOR
-M: Bart Van Assche
+M: Bart Van Assche
L: linux-rdma@vger.kernel.org
S: Supported
W: http://www.openfabrics.org
@@ -9719,6 +9719,11 @@ L: linux-omap@vger.kernel.org
S: Maintained
F: drivers/thermal/ti-soc-thermal/
+TI CDCE706 CLOCK DRIVER
+M: Max Filippov
+S: Maintained
+F: drivers/clk/clk-cdce706.c
+
TI CLOCK DRIVER
M: Tero Kristo
L: linux-omap@vger.kernel.org
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 8ca3c1a2063dee..5c2925831f2038 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -294,35 +294,43 @@
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc0";
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
};
mmc1_clk: clk@01c2008c {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c2008c 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc1";
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
};
mmc2_clk: clk@01c20090 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20090 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc2";
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
};
mmc3_clk: clk@01c20094 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20094 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc3";
+ clock-output-names = "mmc3",
+ "mmc3_output",
+ "mmc3_sample";
};
ts_clk: clk@01c20098 {
@@ -468,8 +476,14 @@
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun4i-a10-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <32>;
status = "disabled";
};
@@ -477,8 +491,14 @@
mmc1: mmc@01c10000 {
compatible = "allwinner,sun4i-a10-mmc";
reg = <0x01c10000 0x1000>;
- clocks = <&ahb_gates 9>, <&mmc1_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <33>;
status = "disabled";
};
@@ -486,8 +506,14 @@
mmc2: mmc@01c11000 {
compatible = "allwinner,sun4i-a10-mmc";
reg = <0x01c11000 0x1000>;
- clocks = <&ahb_gates 10>, <&mmc2_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <34>;
status = "disabled";
};
@@ -495,8 +521,14 @@
mmc3: mmc@01c12000 {
compatible = "allwinner,sun4i-a10-mmc";
reg = <0x01c12000 0x1000>;
- clocks = <&ahb_gates 11>, <&mmc3_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 11>,
+ <&mmc3_clk 0>,
+ <&mmc3_clk 1>,
+ <&mmc3_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <35>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 905f84d141f032..2fd8988f310c6e 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -218,27 +218,33 @@
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc0";
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
};
mmc1_clk: clk@01c2008c {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c2008c 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc1";
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
};
mmc2_clk: clk@01c20090 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20090 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc2";
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
};
ts_clk: clk@01c20098 {
@@ -368,8 +374,14 @@
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <32>;
status = "disabled";
};
@@ -377,8 +389,14 @@
mmc1: mmc@01c10000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c10000 0x1000>;
- clocks = <&ahb_gates 9>, <&mmc1_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <33>;
status = "disabled";
};
@@ -386,8 +404,14 @@
mmc2: mmc@01c11000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c11000 0x1000>;
- clocks = <&ahb_gates 10>, <&mmc2_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <34>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 4910393d1b0901..f8818f1edbbef2 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -257,27 +257,33 @@
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc0";
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
};
mmc1_clk: clk@01c2008c {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c2008c 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc1";
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
};
mmc2_clk: clk@01c20090 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20090 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc2";
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
};
ts_clk: clk@01c20098 {
@@ -391,8 +397,14 @@
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <32>;
status = "disabled";
};
@@ -400,8 +412,14 @@
mmc2: mmc@01c11000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c11000 0x1000>;
- clocks = <&ahb_gates 10>, <&mmc2_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = <34>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 47e557656993fe..fa2f403ccf28ad 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -190,19 +190,11 @@
clock-output-names = "axi";
};
- ahb1_mux: ahb1_mux@01c20054 {
- #clock-cells = <0>;
- compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
- reg = <0x01c20054 0x4>;
- clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
- clock-output-names = "ahb1_mux";
- };
-
ahb1: ahb1@01c20054 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-ahb-clk";
+ compatible = "allwinner,sun6i-a31-ahb1-clk";
reg = <0x01c20054 0x4>;
- clocks = <&ahb1_mux>;
+ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
clock-output-names = "ahb1";
};
@@ -265,35 +257,43 @@
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
clocks = <&osc24M>, <&pll6 0>;
- clock-output-names = "mmc0";
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
};
mmc1_clk: clk@01c2008c {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c2008c 0x4>;
clocks = <&osc24M>, <&pll6 0>;
- clock-output-names = "mmc1";
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
};
mmc2_clk: clk@01c20090 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20090 0x4>;
clocks = <&osc24M>, <&pll6 0>;
- clock-output-names = "mmc2";
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
};
mmc3_clk: clk@01c20094 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20094 0x4>;
clocks = <&osc24M>, <&pll6 0>;
- clock-output-names = "mmc3";
+ clock-output-names = "mmc3",
+ "mmc3_output",
+ "mmc3_sample";
};
spi0_clk: clk@01c200a0 {
@@ -383,15 +383,21 @@
#dma-cells = <1>;
/* DMA controller requires AHB1 clocked from PLL6 */
- assigned-clocks = <&ahb1_mux>;
+ assigned-clocks = <&ahb1>;
assigned-clock-parents = <&pll6 0>;
};
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb1_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 8>;
reset-names = "ahb";
interrupts = ;
@@ -401,8 +407,14 @@
mmc1: mmc@01c10000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c10000 0x1000>;
- clocks = <&ahb1_gates 9>, <&mmc1_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 9>;
reset-names = "ahb";
interrupts = ;
@@ -412,8 +424,14 @@
mmc2: mmc@01c11000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c11000 0x1000>;
- clocks = <&ahb1_gates 10>, <&mmc2_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 10>;
reset-names = "ahb";
interrupts = ;
@@ -423,8 +441,14 @@
mmc3: mmc@01c12000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c12000 0x1000>;
- clocks = <&ahb1_gates 11>, <&mmc3_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 11>,
+ <&mmc3_clk 0>,
+ <&mmc3_clk 1>,
+ <&mmc3_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 11>;
reset-names = "ahb";
interrupts = ;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 786d491542ac42..3a8530b79f1c46 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -337,35 +337,43 @@
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc0";
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
};
mmc1_clk: clk@01c2008c {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c2008c 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc1";
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
};
mmc2_clk: clk@01c20090 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20090 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc2";
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
};
mmc3_clk: clk@01c20094 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20094 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
- clock-output-names = "mmc3";
+ clock-output-names = "mmc3",
+ "mmc3_output",
+ "mmc3_sample";
};
ts_clk: clk@01c20098 {
@@ -583,8 +591,14 @@
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = ;
status = "disabled";
};
@@ -592,8 +606,14 @@
mmc1: mmc@01c10000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c10000 0x1000>;
- clocks = <&ahb_gates 9>, <&mmc1_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = ;
status = "disabled";
};
@@ -601,8 +621,14 @@
mmc2: mmc@01c11000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c11000 0x1000>;
- clocks = <&ahb_gates 10>, <&mmc2_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = ;
status = "disabled";
};
@@ -610,8 +636,14 @@
mmc3: mmc@01c12000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c12000 0x1000>;
- clocks = <&ahb_gates 11>, <&mmc3_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb_gates 11>,
+ <&mmc3_clk 0>,
+ <&mmc3_clk 1>,
+ <&mmc3_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
interrupts = ;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
index dd34527293e465..382ebd137ee4fb 100644
--- a/arch/arm/boot/dts/sun8i-a23.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -119,11 +119,19 @@
};
/* dummy clock until actually implemented */
- pll6: pll6_clk {
+ pll5: pll5_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
- clock-frequency = <600000000>;
- clock-output-names = "pll6";
+ clock-frequency = <0>;
+ clock-output-names = "pll5";
+ };
+
+ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun6i-a31-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6", "pll6x2";
};
cpu: cpu_clk@01c20050 {
@@ -149,19 +157,11 @@
clock-output-names = "axi";
};
- ahb1_mux: ahb1_mux_clk@01c20054 {
- #clock-cells = <0>;
- compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
- reg = <0x01c20054 0x4>;
- clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>;
- clock-output-names = "ahb1_mux";
- };
-
ahb1: ahb1_clk@01c20054 {
#clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-ahb-clk";
+ compatible = "allwinner,sun6i-a31-ahb1-clk";
reg = <0x01c20054 0x4>;
- clocks = <&ahb1_mux>;
+ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
clock-output-names = "ahb1";
};
@@ -202,7 +202,7 @@
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
- clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+ clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
clock-output-names = "apb2";
};
@@ -218,27 +218,41 @@
};
mmc0_clk: clk@01c20088 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20088 0x4>;
- clocks = <&osc24M>, <&pll6>;
- clock-output-names = "mmc0";
+ clocks = <&osc24M>, <&pll6 0>;
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
};
mmc1_clk: clk@01c2008c {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c2008c 0x4>;
- clocks = <&osc24M>, <&pll6>;
- clock-output-names = "mmc1";
+ clocks = <&osc24M>, <&pll6 0>;
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
};
mmc2_clk: clk@01c20090 {
- #clock-cells = <0>;
- compatible = "allwinner,sun4i-a10-mod0-clk";
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
reg = <0x01c20090 0x4>;
- clocks = <&osc24M>, <&pll6>;
- clock-output-names = "mmc2";
+ clocks = <&osc24M>, <&pll6 0>;
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
+ };
+
+ mbus_clk: clk@01c2015c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-a23-mbus-clk";
+ reg = <0x01c2015c 0x4>;
+ clocks = <&osc24M>, <&pll6 1>, <&pll5>;
+ clock-output-names = "mbus";
};
};
@@ -260,8 +274,14 @@
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- clocks = <&ahb1_gates 8>, <&mmc0_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 8>;
reset-names = "ahb";
interrupts = ;
@@ -271,8 +291,14 @@
mmc1: mmc@01c10000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c10000 0x1000>;
- clocks = <&ahb1_gates 9>, <&mmc1_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 9>;
reset-names = "ahb";
interrupts = ;
@@ -282,8 +308,14 @@
mmc2: mmc@01c11000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c11000 0x1000>;
- clocks = <&ahb1_gates 10>, <&mmc2_clk>;
- clock-names = "ahb", "mmc";
+ clocks = <&ahb1_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
resets = <&ahb1_rst 10>;
reset-names = "ahb";
interrupts = ;
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 00d5d8f9f150ed..b83f18fcec9b3c 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -190,7 +190,7 @@ obj-$(CONFIG_SOC_OMAP2430) += clock2430.o
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
-obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o cclock3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o
obj-$(CONFIG_ARCH_OMAP4) += $(clock-common)
obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
deleted file mode 100644
index e79c80bbc7555a..00000000000000
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ /dev/null
@@ -1,3688 +0,0 @@
-/*
- * OMAP3 clock data
- *
- * Copyright (C) 2007-2012 Texas Instruments, Inc.
- * Copyright (C) 2007-2011 Nokia Corporation
- *
- * Written by Paul Walmsley
- * Updated to COMMON clk data format by Rajendra Nayak
- * With many device clock fixes by Kevin Hilman and Jouni Högander
- * DPLL bypass clock support added by Roman Tereshonkov
- *
- */
-
-/*
- * Virtual clocks are introduced as convenient tools.
- * They are sources for other clocks and not supposed
- * to be requested from drivers directly.
- */
-
-#include
-#include
-#include
-#include
-#include
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock3xxx.h"
-#include "clock34xx.h"
-#include "clock36xx.h"
-#include "clock3517.h"
-#include "cm3xxx.h"
-#include "cm-regbits-34xx.h"
-#include "prm3xxx.h"
-#include "prm-regbits-34xx.h"
-#include "control.h"
-
-/*
- * clocks
- */
-
-#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR
-
-/* Maximum DPLL multiplier, divider values for OMAP3 */
-#define OMAP3_MAX_DPLL_MULT 2047
-#define OMAP3630_MAX_JTYPE_DPLL_MULT 4095
-#define OMAP3_MAX_DPLL_DIV 128
-
-DEFINE_CLK_FIXED_RATE(dummy_apb_pclk, CLK_IS_ROOT, 0x0, 0x0);
-
-DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
-
-DEFINE_CLK_FIXED_RATE(omap_32k_fck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(pclk_ck, CLK_IS_ROOT, 27000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(rmii_ck, CLK_IS_ROOT, 50000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(secure_32k_fck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(sys_altclk, CLK_IS_ROOT, 0x0, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_12m_ck, CLK_IS_ROOT, 12000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_13m_ck, CLK_IS_ROOT, 13000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_16_8m_ck, CLK_IS_ROOT, 16800000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_38_4m_ck, CLK_IS_ROOT, 38400000, 0x0);
-
-static const char *osc_sys_ck_parent_names[] = {
- "virt_12m_ck", "virt_13m_ck", "virt_19200000_ck", "virt_26000000_ck",
- "virt_38_4m_ck", "virt_16_8m_ck",
-};
-
-DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0,
- OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT,
- OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0,
- OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT,
- OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct dpll_data dpll3_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_CORE_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP3430_EN_CORE_DPLL_MASK,
- .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
- .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
- .idlest_mask = OMAP3430_ST_CORE_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll3_ck;
-
-static const char *dpll3_ck_parent_names[] = {
- "sys_ck",
- "sys_ck",
-};
-
-static const struct clk_ops dpll3_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .get_parent = &omap2_init_dpll_parent,
- .recalc_rate = &omap3_dpll_recalc,
- .round_rate = &omap2_dpll_round_rate,
-};
-
-static struct clk_hw_omap dpll3_ck_hw = {
- .hw = {
- .clk = &dpll3_ck,
- },
- .ops = &clkhwops_omap3_dpll,
- .dpll_data = &dpll3_dd,
- .clkdm_name = "dpll3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops);
-
-DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT,
- OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk core_ck;
-
-static const char *core_ck_parent_names[] = {
- "dpll3_m2_ck",
-};
-
-static const struct clk_ops core_ck_ops = {};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL);
-DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
-
-DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk security_l4_ick2;
-
-static const char *security_l4_ick2_parent_names[] = {
- "l4_ick",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(security_l4_ick2, NULL);
-DEFINE_STRUCT_CLK(security_l4_ick2, security_l4_ick2_parent_names, core_ck_ops);
-
-static struct clk aes1_ick;
-
-static const char *aes1_ick_parent_names[] = {
- "security_l4_ick2",
-};
-
-static const struct clk_ops aes1_ick_ops = {
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap aes1_ick_hw = {
- .hw = {
- .clk = &aes1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_AES1_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(aes1_ick, aes1_ick_parent_names, aes1_ick_ops);
-
-static struct clk core_l4_ick;
-
-static const struct clk_ops core_l4_ick_ops = {
- .init = &omap2_init_clk_clkdm,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_l4_ick, "core_l4_clkdm");
-DEFINE_STRUCT_CLK(core_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
-
-static struct clk aes2_ick;
-
-static const char *aes2_ick_parent_names[] = {
- "core_l4_ick",
-};
-
-static const struct clk_ops aes2_ick_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap aes2_ick_hw = {
- .hw = {
- .clk = &aes2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_AES2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(aes2_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk dpll1_fck;
-
-static struct dpll_data dpll1_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
- .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK,
- .clk_bypass = &dpll1_fck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_MPU_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
- .enable_mask = OMAP3430_EN_MPU_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
- .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
- .idlest_mask = OMAP3430_ST_MPU_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll1_ck;
-
-static const struct clk_ops dpll1_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap3_noncore_dpll_enable,
- .disable = &omap3_noncore_dpll_disable,
- .get_parent = &omap2_init_dpll_parent,
- .recalc_rate = &omap3_dpll_recalc,
- .set_rate = &omap3_noncore_dpll_set_rate,
- .set_parent = &omap3_noncore_dpll_set_parent,
- .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent,
- .determine_rate = &omap3_noncore_dpll_determine_rate,
- .round_rate = &omap2_dpll_round_rate,
-};
-
-static struct clk_hw_omap dpll1_ck_hw = {
- .hw = {
- .clk = &dpll1_ck,
- },
- .ops = &clkhwops_omap3_dpll,
- .dpll_data = &dpll1_dd,
- .clkdm_name = "dpll1_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops);
-
-DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1);
-
-DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0,
- OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
- OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT,
- OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk mpu_ck;
-
-static const char *mpu_ck_parent_names[] = {
- "dpll1_x2m2_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, "mpu_clkdm");
-DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops);
-
-DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck, 0x0,
- OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
- OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH,
- 0x0, NULL);
-
-static struct clk cam_ick;
-
-static struct clk_hw_omap cam_ick_hw = {
- .hw = {
- .clk = &cam_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_CAM_SHIFT,
- .clkdm_name = "cam_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_ick, security_l4_ick2_parent_names, aes2_ick_ops);
-
-/* DPLL4 */
-/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
-/* Type: DPLL */
-static struct dpll_data dpll4_dd;
-
-static struct dpll_data dpll4_dd_34xx __initdata = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
- .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
- .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
- .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct dpll_data dpll4_dd_3630 __initdata = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
- .mult_mask = OMAP3630_PERIPH_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
- .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
- .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
- .dco_mask = OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
- .sddiv_mask = OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
- .max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
- .flags = DPLL_J_TYPE
-};
-
-static struct clk dpll4_ck;
-
-static const struct clk_ops dpll4_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap3_noncore_dpll_enable,
- .disable = &omap3_noncore_dpll_disable,
- .get_parent = &omap2_init_dpll_parent,
- .recalc_rate = &omap3_dpll_recalc,
- .set_rate = &omap3_dpll4_set_rate,
- .set_parent = &omap3_noncore_dpll_set_parent,
- .set_rate_and_parent = &omap3_dpll4_set_rate_and_parent,
- .determine_rate = &omap3_noncore_dpll_determine_rate,
- .round_rate = &omap2_dpll_round_rate,
-};
-
-static struct clk_hw_omap dpll4_ck_hw = {
- .hw = {
- .clk = &dpll4_ck,
- },
- .dpll_data = &dpll4_dd,
- .ops = &clkhwops_omap3_dpll,
- .clkdm_name = "dpll4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll4_ck, dpll3_ck_parent_names, dpll4_ck_ops);
-
-static const struct clk_div_table dpll4_mx_ck_div_table[] = {
- { .div = 1, .val = 1 },
- { .div = 2, .val = 2 },
- { .div = 3, .val = 3 },
- { .div = 4, .val = 4 },
- { .div = 5, .val = 5 },
- { .div = 6, .val = 6 },
- { .div = 7, .val = 7 },
- { .div = 8, .val = 8 },
- { .div = 9, .val = 9 },
- { .div = 10, .val = 10 },
- { .div = 11, .val = 11 },
- { .div = 12, .val = 12 },
- { .div = 13, .val = 13 },
- { .div = 14, .val = 14 },
- { .div = 15, .val = 15 },
- { .div = 16, .val = 16 },
- { .div = 17, .val = 17 },
- { .div = 18, .val = 18 },
- { .div = 19, .val = 19 },
- { .div = 20, .val = 20 },
- { .div = 21, .val = 21 },
- { .div = 22, .val = 22 },
- { .div = 23, .val = 23 },
- { .div = 24, .val = 24 },
- { .div = 25, .val = 25 },
- { .div = 26, .val = 26 },
- { .div = 27, .val = 27 },
- { .div = 28, .val = 28 },
- { .div = 29, .val = 29 },
- { .div = 30, .val = 30 },
- { .div = 31, .val = 31 },
- { .div = 32, .val = 32 },
- { .div = 0 },
-};
-
-DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk dpll4_m5x2_ck;
-
-static const char *dpll4_m5x2_ck_parent_names[] = {
- "dpll4_m5_ck",
-};
-
-static const struct clk_ops dpll4_m5x2_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .set_rate = &omap3_clkoutx2_set_rate,
- .recalc_rate = &omap3_clkoutx2_recalc,
- .round_rate = &omap3_clkoutx2_round_rate,
-};
-
-static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap36xx_pwrdn_clk_enable_with_hsdiv_restore,
- .disable = &omap2_dflt_clk_disable,
- .recalc_rate = &omap3_clkoutx2_recalc,
-};
-
-static struct clk_hw_omap dpll4_m5x2_ck_hw = {
- .hw = {
- .clk = &dpll4_m5x2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_CAM_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
-};
-
-DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names,
- dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
-
-static struct clk dpll4_m5x2_ck_3630 = {
- .name = "dpll4_m5x2_ck",
- .hw = &dpll4_m5x2_ck_hw.hw,
- .parent_names = dpll4_m5x2_ck_parent_names,
- .num_parents = ARRAY_SIZE(dpll4_m5x2_ck_parent_names),
- .ops = &dpll4_m5x2_ck_3630_ops,
- .flags = CLK_SET_RATE_PARENT,
-};
-
-static struct clk cam_mclk;
-
-static const char *cam_mclk_parent_names[] = {
- "dpll4_m5x2_ck",
-};
-
-static struct clk_hw_omap cam_mclk_hw = {
- .hw = {
- .clk = &cam_mclk,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_CAM_SHIFT,
- .clkdm_name = "cam_clkdm",
-};
-
-static struct clk cam_mclk = {
- .name = "cam_mclk",
- .hw = &cam_mclk_hw.hw,
- .parent_names = cam_mclk_parent_names,
- .num_parents = ARRAY_SIZE(cam_mclk_parent_names),
- .ops = &aes2_ick_ops,
- .flags = CLK_SET_RATE_PARENT,
-};
-
-static const struct clksel_rate clkout2_src_core_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate clkout2_src_96m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
- OMAP3430_DIV_96M_SHIFT, OMAP3630_DIV_96M_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk dpll4_m2x2_ck;
-
-static const char *dpll4_m2x2_ck_parent_names[] = {
- "dpll4_m2_ck",
-};
-
-static struct clk_hw_omap dpll4_m2x2_ck_hw = {
- .hw = {
- .clk = &dpll4_m2x2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_96M_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll4_m2x2_ck, dpll4_m2x2_ck_parent_names, dpll4_m5x2_ck_ops);
-
-static struct clk dpll4_m2x2_ck_3630 = {
- .name = "dpll4_m2x2_ck",
- .hw = &dpll4_m2x2_ck_hw.hw,
- .parent_names = dpll4_m2x2_ck_parent_names,
- .num_parents = ARRAY_SIZE(dpll4_m2x2_ck_parent_names),
- .ops = &dpll4_m5x2_ck_3630_ops,
-};
-
-static struct clk omap_96m_alwon_fck;
-
-static const char *omap_96m_alwon_fck_parent_names[] = {
- "dpll4_m2x2_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(omap_96m_alwon_fck, NULL);
-DEFINE_STRUCT_CLK(omap_96m_alwon_fck, omap_96m_alwon_fck_parent_names,
- core_ck_ops);
-
-static struct clk cm_96m_fck;
-
-static const char *cm_96m_fck_parent_names[] = {
- "omap_96m_alwon_fck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(cm_96m_fck, NULL);
-DEFINE_STRUCT_CLK(cm_96m_fck, cm_96m_fck_parent_names, core_ck_ops);
-
-static const struct clksel_rate clkout2_src_54m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH,
- 0, dpll4_mx_ck_div_table, NULL);
-
-static struct clk dpll4_m3x2_ck;
-
-static const char *dpll4_m3x2_ck_parent_names[] = {
- "dpll4_m3_ck",
-};
-
-static struct clk_hw_omap dpll4_m3x2_ck_hw = {
- .hw = {
- .clk = &dpll4_m3x2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_TV_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll4_m3x2_ck, dpll4_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
-
-static struct clk dpll4_m3x2_ck_3630 = {
- .name = "dpll4_m3x2_ck",
- .hw = &dpll4_m3x2_ck_hw.hw,
- .parent_names = dpll4_m3x2_ck_parent_names,
- .num_parents = ARRAY_SIZE(dpll4_m3x2_ck_parent_names),
- .ops = &dpll4_m5x2_ck_3630_ops,
-};
-
-static const char *omap_54m_fck_parent_names[] = {
- "dpll4_m3x2_ck", "sys_altclk",
-};
-
-DEFINE_CLK_MUX(omap_54m_fck, omap_54m_fck_parent_names, NULL, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP3430_SOURCE_54M_SHIFT,
- OMAP3430_SOURCE_54M_WIDTH, 0x0, NULL);
-
-static const struct clksel clkout2_src_clksel[] = {
- { .parent = &core_ck, .rates = clkout2_src_core_rates },
- { .parent = &sys_ck, .rates = clkout2_src_sys_rates },
- { .parent = &cm_96m_fck, .rates = clkout2_src_96m_rates },
- { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates },
- { .parent = NULL },
-};
-
-static const char *clkout2_src_ck_parent_names[] = {
- "core_ck", "sys_ck", "cm_96m_fck", "omap_54m_fck",
-};
-
-static const struct clk_ops clkout2_src_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(clkout2_src_ck, "core_clkdm",
- clkout2_src_clksel, OMAP3430_CM_CLKOUT_CTRL,
- OMAP3430_CLKOUT2SOURCE_MASK,
- OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_EN_SHIFT,
- NULL, clkout2_src_ck_parent_names, clkout2_src_ck_ops);
-
-static const struct clksel_rate omap_48m_cm96m_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate omap_48m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel omap_48m_clksel[] = {
- { .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates },
- { .parent = &sys_altclk, .rates = omap_48m_alt_rates },
- { .parent = NULL },
-};
-
-static const char *omap_48m_fck_parent_names[] = {
- "cm_96m_fck", "sys_altclk",
-};
-
-static struct clk omap_48m_fck;
-
-static const struct clk_ops omap_48m_fck_ops = {
- .recalc_rate = &omap2_clksel_recalc,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-static struct clk_hw_omap omap_48m_fck_hw = {
- .hw = {
- .clk = &omap_48m_fck,
- },
- .clksel = omap_48m_clksel,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_SOURCE_48M_MASK,
-};
-
-DEFINE_STRUCT_CLK(omap_48m_fck, omap_48m_fck_parent_names, omap_48m_fck_ops);
-
-DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck, 0x0, 1, 4);
-
-static struct clk core_12m_fck;
-
-static const char *core_12m_fck_parent_names[] = {
- "omap_12m_fck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_12m_fck, "core_l4_clkdm");
-DEFINE_STRUCT_CLK(core_12m_fck, core_12m_fck_parent_names, core_l4_ick_ops);
-
-static struct clk core_48m_fck;
-
-static const char *core_48m_fck_parent_names[] = {
- "omap_48m_fck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_48m_fck, "core_l4_clkdm");
-DEFINE_STRUCT_CLK(core_48m_fck, core_48m_fck_parent_names, core_l4_ick_ops);
-
-static const char *omap_96m_fck_parent_names[] = {
- "cm_96m_fck", "sys_ck",
-};
-
-DEFINE_CLK_MUX(omap_96m_fck, omap_96m_fck_parent_names, NULL, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- OMAP3430_SOURCE_96M_SHIFT, OMAP3430_SOURCE_96M_WIDTH, 0x0, NULL);
-
-static struct clk core_96m_fck;
-
-static const char *core_96m_fck_parent_names[] = {
- "omap_96m_fck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_96m_fck, "core_l4_clkdm");
-DEFINE_STRUCT_CLK(core_96m_fck, core_96m_fck_parent_names, core_l4_ick_ops);
-
-static struct clk core_l3_ick;
-
-static const char *core_l3_ick_parent_names[] = {
- "l3_ick",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_l3_ick, "core_l3_clkdm");
-DEFINE_STRUCT_CLK(core_l3_ick, core_l3_ick_parent_names, core_l4_ick_ops);
-
-DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck, 0x0, 2, 1);
-
-static struct clk corex2_fck;
-
-static const char *corex2_fck_parent_names[] = {
- "dpll3_m2x2_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(corex2_fck, NULL);
-DEFINE_STRUCT_CLK(corex2_fck, corex2_fck_parent_names, core_ck_ops);
-
-static const char *cpefuse_fck_parent_names[] = {
- "sys_ck",
-};
-
-static struct clk cpefuse_fck;
-
-static struct clk_hw_omap cpefuse_fck_hw = {
- .hw = {
- .clk = &cpefuse_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
- .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cpefuse_fck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk csi2_96m_fck;
-
-static const char *csi2_96m_fck_parent_names[] = {
- "core_96m_fck",
-};
-
-static struct clk_hw_omap csi2_96m_fck_hw = {
- .hw = {
- .clk = &csi2_96m_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_CSI2_SHIFT,
- .clkdm_name = "cam_clkdm",
-};
-
-DEFINE_STRUCT_CLK(csi2_96m_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk d2d_26m_fck;
-
-static struct clk_hw_omap d2d_26m_fck_hw = {
- .hw = {
- .clk = &d2d_26m_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430ES1_EN_D2D_SHIFT,
- .clkdm_name = "d2d_clkdm",
-};
-
-DEFINE_STRUCT_CLK(d2d_26m_fck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk des1_ick;
-
-static struct clk_hw_omap des1_ick_hw = {
- .hw = {
- .clk = &des1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_DES1_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(des1_ick, aes1_ick_parent_names, aes1_ick_ops);
-
-static struct clk des2_ick;
-
-static struct clk_hw_omap des2_ick_hw = {
- .hw = {
- .clk = &des2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_DES2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(des2_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
- OMAP3430_MPU_CLK_SRC_SHIFT, OMAP3430_MPU_CLK_SRC_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk dpll2_fck;
-
-static struct dpll_data dpll2_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
- .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK,
- .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK,
- .clk_bypass = &dpll2_fck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430_IVA2_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
- .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK,
- .modes = ((1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
- (1 << DPLL_LOW_POWER_BYPASS)),
- .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
- .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
- .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll2_ck;
-
-static struct clk_hw_omap dpll2_ck_hw = {
- .hw = {
- .clk = &dpll2_ck,
- },
- .ops = &clkhwops_omap3_dpll,
- .dpll_data = &dpll2_dd,
- .clkdm_name = "dpll2_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll2_ck, dpll3_ck_parent_names, dpll1_ck_ops);
-
-DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
- OMAP3430_IVA2_CLK_SRC_SHIFT, OMAP3430_IVA2_CLK_SRC_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL),
- OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT,
- OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_DIV_DPLL3_SHIFT, OMAP3430_DIV_DPLL3_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk dpll3_m3x2_ck;
-
-static const char *dpll3_m3x2_ck_parent_names[] = {
- "dpll3_m3_ck",
-};
-
-static struct clk_hw_omap dpll3_m3x2_ck_hw = {
- .hw = {
- .clk = &dpll3_m3x2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll3_m3x2_ck, dpll3_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
-
-static struct clk dpll3_m3x2_ck_3630 = {
- .name = "dpll3_m3x2_ck",
- .hw = &dpll3_m3x2_ck_hw.hw,
- .parent_names = dpll3_m3x2_ck_parent_names,
- .num_parents = ARRAY_SIZE(dpll3_m3x2_ck_parent_names),
- .ops = &dpll4_m5x2_ck_3630_ops,
-};
-
-DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1);
-
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH,
- 0, dpll4_mx_ck_div_table, NULL);
-
-static struct clk dpll4_m4x2_ck;
-
-static const char *dpll4_m4x2_ck_parent_names[] = {
- "dpll4_m4_ck",
-};
-
-static struct clk_hw_omap dpll4_m4x2_ck_hw = {
- .hw = {
- .clk = &dpll4_m4x2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_DSS1_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
-};
-
-DEFINE_STRUCT_CLK_FLAGS(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names,
- dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
-
-static struct clk dpll4_m4x2_ck_3630 = {
- .name = "dpll4_m4x2_ck",
- .hw = &dpll4_m4x2_ck_hw.hw,
- .parent_names = dpll4_m4x2_ck_parent_names,
- .num_parents = ARRAY_SIZE(dpll4_m4x2_ck_parent_names),
- .ops = &dpll4_m5x2_ck_3630_ops,
- .flags = CLK_SET_RATE_PARENT,
-};
-
-DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_DIV_DPLL4_SHIFT, OMAP3630_DIV_DPLL4_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk dpll4_m6x2_ck;
-
-static const char *dpll4_m6x2_ck_parent_names[] = {
- "dpll4_m6_ck",
-};
-
-static struct clk_hw_omap dpll4_m6x2_ck_hw = {
- .hw = {
- .clk = &dpll4_m6x2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
- .flags = INVERT_ENABLE,
- .clkdm_name = "dpll4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll4_m6x2_ck, dpll4_m6x2_ck_parent_names, dpll4_m5x2_ck_ops);
-
-static struct clk dpll4_m6x2_ck_3630 = {
- .name = "dpll4_m6x2_ck",
- .hw = &dpll4_m6x2_ck_hw.hw,
- .parent_names = dpll4_m6x2_ck_parent_names,
- .num_parents = ARRAY_SIZE(dpll4_m6x2_ck_parent_names),
- .ops = &dpll4_m5x2_ck_3630_ops,
-};
-
-DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck, 0x0, 2, 1);
-
-static struct dpll_data dpll5_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
- .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
- .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .freqsel_mask = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
- .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
- .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
- .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
- .recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
- .recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
- .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
- .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
- .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
- .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
- .max_multiplier = OMAP3_MAX_DPLL_MULT,
- .min_divider = 1,
- .max_divider = OMAP3_MAX_DPLL_DIV,
-};
-
-static struct clk dpll5_ck;
-
-static struct clk_hw_omap dpll5_ck_hw = {
- .hw = {
- .clk = &dpll5_ck,
- },
- .ops = &clkhwops_omap3_dpll,
- .dpll_data = &dpll5_dd,
- .clkdm_name = "dpll5_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll5_ck, dpll3_ck_parent_names, dpll1_ck_ops);
-
-DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
- OMAP3430ES2_DIV_120M_SHIFT, OMAP3430ES2_DIV_120M_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk dss1_alwon_fck_3430es1;
-
-static const char *dss1_alwon_fck_3430es1_parent_names[] = {
- "dpll4_m4x2_ck",
-};
-
-static struct clk_hw_omap dss1_alwon_fck_3430es1_hw = {
- .hw = {
- .clk = &dss1_alwon_fck_3430es1,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_DSS1_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK_FLAGS(dss1_alwon_fck_3430es1,
- dss1_alwon_fck_3430es1_parent_names, aes2_ick_ops,
- CLK_SET_RATE_PARENT);
-
-static struct clk dss1_alwon_fck_3430es2;
-
-static struct clk_hw_omap dss1_alwon_fck_3430es2_hw = {
- .hw = {
- .clk = &dss1_alwon_fck_3430es2,
- },
- .ops = &clkhwops_omap3430es2_dss_usbhost_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_DSS1_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK_FLAGS(dss1_alwon_fck_3430es2,
- dss1_alwon_fck_3430es1_parent_names, aes2_ick_ops,
- CLK_SET_RATE_PARENT);
-
-static struct clk dss2_alwon_fck;
-
-static struct clk_hw_omap dss2_alwon_fck_hw = {
- .hw = {
- .clk = &dss2_alwon_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_DSS2_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss2_alwon_fck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk dss_96m_fck;
-
-static struct clk_hw_omap dss_96m_fck_hw = {
- .hw = {
- .clk = &dss_96m_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_TV_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_96m_fck, core_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk dss_ick_3430es1;
-
-static struct clk_hw_omap dss_ick_3430es1_hw = {
- .hw = {
- .clk = &dss_ick_3430es1,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_ick_3430es1, security_l4_ick2_parent_names, aes2_ick_ops);
-
-static struct clk dss_ick_3430es2;
-
-static struct clk_hw_omap dss_ick_3430es2_hw = {
- .hw = {
- .clk = &dss_ick_3430es2,
- },
- .ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_ick_3430es2, security_l4_ick2_parent_names, aes2_ick_ops);
-
-static struct clk dss_tv_fck;
-
-static const char *dss_tv_fck_parent_names[] = {
- "omap_54m_fck",
-};
-
-static struct clk_hw_omap dss_tv_fck_hw = {
- .hw = {
- .clk = &dss_tv_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_TV_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_tv_fck, dss_tv_fck_parent_names, aes2_ick_ops);
-
-static struct clk emac_fck;
-
-static const char *emac_fck_parent_names[] = {
- "rmii_ck",
-};
-
-static struct clk_hw_omap emac_fck_hw = {
- .hw = {
- .clk = &emac_fck,
- },
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_CPGMAC_FCLK_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(emac_fck, emac_fck_parent_names, aes1_ick_ops);
-
-static struct clk ipss_ick;
-
-static const char *ipss_ick_parent_names[] = {
- "core_l3_ick",
-};
-
-static struct clk_hw_omap ipss_ick_hw = {
- .hw = {
- .clk = &ipss_ick,
- },
- .ops = &clkhwops_am35xx_ipss_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = AM35XX_EN_IPSS_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ipss_ick, ipss_ick_parent_names, aes2_ick_ops);
-
-static struct clk emac_ick;
-
-static const char *emac_ick_parent_names[] = {
- "ipss_ick",
-};
-
-static struct clk_hw_omap emac_ick_hw = {
- .hw = {
- .clk = &emac_ick,
- },
- .ops = &clkhwops_am35xx_ipss_module_wait,
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_CPGMAC_VBUSP_CLK_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(emac_ick, emac_ick_parent_names, aes2_ick_ops);
-
-static struct clk emu_core_alwon_ck;
-
-static const char *emu_core_alwon_ck_parent_names[] = {
- "dpll3_m3x2_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(emu_core_alwon_ck, "dpll3_clkdm");
-DEFINE_STRUCT_CLK(emu_core_alwon_ck, emu_core_alwon_ck_parent_names,
- core_l4_ick_ops);
-
-static struct clk emu_mpu_alwon_ck;
-
-static const char *emu_mpu_alwon_ck_parent_names[] = {
- "mpu_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(emu_mpu_alwon_ck, NULL);
-DEFINE_STRUCT_CLK(emu_mpu_alwon_ck, emu_mpu_alwon_ck_parent_names, core_ck_ops);
-
-static struct clk emu_per_alwon_ck;
-
-static const char *emu_per_alwon_ck_parent_names[] = {
- "dpll4_m6x2_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(emu_per_alwon_ck, "dpll4_clkdm");
-DEFINE_STRUCT_CLK(emu_per_alwon_ck, emu_per_alwon_ck_parent_names,
- core_l4_ick_ops);
-
-static const char *emu_src_ck_parent_names[] = {
- "sys_ck", "emu_core_alwon_ck", "emu_per_alwon_ck", "emu_mpu_alwon_ck",
-};
-
-static const struct clksel_rate emu_src_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate emu_src_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate emu_src_per_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel_rate emu_src_mpu_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 },
-};
-
-static const struct clksel emu_src_clksel[] = {
- { .parent = &sys_ck, .rates = emu_src_sys_rates },
- { .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
- { .parent = &emu_per_alwon_ck, .rates = emu_src_per_rates },
- { .parent = &emu_mpu_alwon_ck, .rates = emu_src_mpu_rates },
- { .parent = NULL },
-};
-
-static const struct clk_ops emu_src_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .recalc_rate = &omap2_clksel_recalc,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
- .enable = &omap2_clkops_enable_clkdm,
- .disable = &omap2_clkops_disable_clkdm,
-};
-
-static struct clk emu_src_ck;
-
-static struct clk_hw_omap emu_src_ck_hw = {
- .hw = {
- .clk = &emu_src_ck,
- },
- .clksel = emu_src_clksel,
- .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_MUX_CTRL_MASK,
- .clkdm_name = "emu_clkdm",
-};
-
-DEFINE_STRUCT_CLK(emu_src_ck, emu_src_ck_parent_names, emu_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_CLKSEL_ATCLK_SHIFT, OMAP3430_CLKSEL_ATCLK_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk fac_ick;
-
-static struct clk_hw_omap fac_ick_hw = {
- .hw = {
- .clk = &fac_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430ES1_EN_FAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk fshostusb_fck;
-
-static const char *fshostusb_fck_parent_names[] = {
- "core_48m_fck",
-};
-
-static struct clk_hw_omap fshostusb_fck_hw = {
- .hw = {
- .clk = &fshostusb_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fshostusb_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk gfx_l3_ck;
-
-static struct clk_hw_omap gfx_l3_ck_hw = {
- .hw = {
- .clk = &gfx_l3_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
- .enable_bit = OMAP_EN_GFX_SHIFT,
- .clkdm_name = "gfx_3430es1_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_l3_ck, core_l3_ick_parent_names, aes1_ick_ops);
-
-DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick, 0x0,
- OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- OMAP_CLKSEL_GFX_SHIFT, OMAP_CLKSEL_GFX_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk gfx_cg1_ck;
-
-static const char *gfx_cg1_ck_parent_names[] = {
- "gfx_l3_fck",
-};
-
-static struct clk_hw_omap gfx_cg1_ck_hw = {
- .hw = {
- .clk = &gfx_cg1_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES1_EN_2D_SHIFT,
- .clkdm_name = "gfx_3430es1_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_cg1_ck, gfx_cg1_ck_parent_names, aes2_ick_ops);
-
-static struct clk gfx_cg2_ck;
-
-static struct clk_hw_omap gfx_cg2_ck_hw = {
- .hw = {
- .clk = &gfx_cg2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES1_EN_3D_SHIFT,
- .clkdm_name = "gfx_3430es1_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_cg2_ck, gfx_cg1_ck_parent_names, aes2_ick_ops);
-
-static struct clk gfx_l3_ick;
-
-static const char *gfx_l3_ick_parent_names[] = {
- "gfx_l3_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(gfx_l3_ick, "gfx_3430es1_clkdm");
-DEFINE_STRUCT_CLK(gfx_l3_ick, gfx_l3_ick_parent_names, core_l4_ick_ops);
-
-static struct clk wkup_32k_fck;
-
-static const char *wkup_32k_fck_parent_names[] = {
- "omap_32k_fck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(wkup_32k_fck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(wkup_32k_fck, wkup_32k_fck_parent_names, core_l4_ick_ops);
-
-static struct clk gpio1_dbck;
-
-static const char *gpio1_dbck_parent_names[] = {
- "wkup_32k_fck",
-};
-
-static struct clk_hw_omap gpio1_dbck_hw = {
- .hw = {
- .clk = &gpio1_dbck,
- },
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio1_dbck, gpio1_dbck_parent_names, aes2_ick_ops);
-
-static struct clk wkup_l4_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(wkup_l4_ick, "wkup_clkdm");
-DEFINE_STRUCT_CLK(wkup_l4_ick, cpefuse_fck_parent_names, core_l4_ick_ops);
-
-static struct clk gpio1_ick;
-
-static const char *gpio1_ick_parent_names[] = {
- "wkup_l4_ick",
-};
-
-static struct clk_hw_omap gpio1_ick_hw = {
- .hw = {
- .clk = &gpio1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio1_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-static struct clk per_32k_alwon_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(per_32k_alwon_fck, "per_clkdm");
-DEFINE_STRUCT_CLK(per_32k_alwon_fck, wkup_32k_fck_parent_names,
- core_l4_ick_ops);
-
-static struct clk gpio2_dbck;
-
-static const char *gpio2_dbck_parent_names[] = {
- "per_32k_alwon_fck",
-};
-
-static struct clk_hw_omap gpio2_dbck_hw = {
- .hw = {
- .clk = &gpio2_dbck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio2_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
-
-static struct clk per_l4_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(per_l4_ick, "per_clkdm");
-DEFINE_STRUCT_CLK(per_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
-
-static struct clk gpio2_ick;
-
-static const char *gpio2_ick_parent_names[] = {
- "per_l4_ick",
-};
-
-static struct clk_hw_omap gpio2_ick_hw = {
- .hw = {
- .clk = &gpio2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio2_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk gpio3_dbck;
-
-static struct clk_hw_omap gpio3_dbck_hw = {
- .hw = {
- .clk = &gpio3_dbck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio3_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
-
-static struct clk gpio3_ick;
-
-static struct clk_hw_omap gpio3_ick_hw = {
- .hw = {
- .clk = &gpio3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio3_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk gpio4_dbck;
-
-static struct clk_hw_omap gpio4_dbck_hw = {
- .hw = {
- .clk = &gpio4_dbck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio4_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
-
-static struct clk gpio4_ick;
-
-static struct clk_hw_omap gpio4_ick_hw = {
- .hw = {
- .clk = &gpio4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio4_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk gpio5_dbck;
-
-static struct clk_hw_omap gpio5_dbck_hw = {
- .hw = {
- .clk = &gpio5_dbck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio5_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
-
-static struct clk gpio5_ick;
-
-static struct clk_hw_omap gpio5_ick_hw = {
- .hw = {
- .clk = &gpio5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio5_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk gpio6_dbck;
-
-static struct clk_hw_omap gpio6_dbck_hw = {
- .hw = {
- .clk = &gpio6_dbck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio6_dbck, gpio2_dbck_parent_names, aes2_ick_ops);
-
-static struct clk gpio6_ick;
-
-static struct clk_hw_omap gpio6_ick_hw = {
- .hw = {
- .clk = &gpio6_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio6_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk gpmc_fck;
-
-static struct clk_hw_omap gpmc_fck_hw = {
- .hw = {
- .clk = &gpmc_fck,
- },
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpmc_fck, ipss_ick_parent_names, core_l4_ick_ops);
-
-static const struct clksel omap343x_gpt_clksel[] = {
- { .parent = &omap_32k_fck, .rates = gpt_32k_rates },
- { .parent = &sys_ck, .rates = gpt_sys_rates },
- { .parent = NULL },
-};
-
-static const char *gpt10_fck_parent_names[] = {
- "omap_32k_fck", "sys_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT10_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP3430_EN_GPT10_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt10_ick;
-
-static struct clk_hw_omap gpt10_ick_hw = {
- .hw = {
- .clk = &gpt10_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_GPT10_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt10_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT11_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP3430_EN_GPT11_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt11_ick;
-
-static struct clk_hw_omap gpt11_ick_hw = {
- .hw = {
- .clk = &gpt11_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_GPT11_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt11_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk gpt12_fck;
-
-static const char *gpt12_fck_parent_names[] = {
- "secure_32k_fck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(gpt12_fck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(gpt12_fck, gpt12_fck_parent_names, core_l4_ick_ops);
-
-static struct clk gpt12_ick;
-
-static struct clk_hw_omap gpt12_ick_hw = {
- .hw = {
- .clk = &gpt12_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT12_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt12_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "wkup_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT1_MASK,
- OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT1_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt1_ick;
-
-static struct clk_hw_omap gpt1_ick_hw = {
- .hw = {
- .clk = &gpt1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt1_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT2_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT2_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt2_ick;
-
-static struct clk_hw_omap gpt2_ick_hw = {
- .hw = {
- .clk = &gpt2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT2_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt2_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT3_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT3_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt3_ick;
-
-static struct clk_hw_omap gpt3_ick_hw = {
- .hw = {
- .clk = &gpt3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt3_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT4_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT4_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt4_ick;
-
-static struct clk_hw_omap gpt4_ick_hw = {
- .hw = {
- .clk = &gpt4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT4_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt4_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT5_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT5_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt5_ick;
-
-static struct clk_hw_omap gpt5_ick_hw = {
- .hw = {
- .clk = &gpt5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT5_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt5_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT6_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT6_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt6_ick;
-
-static struct clk_hw_omap gpt6_ick_hw = {
- .hw = {
- .clk = &gpt6_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT6_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt6_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT7_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT7_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt7_ick;
-
-static struct clk_hw_omap gpt7_ick_hw = {
- .hw = {
- .clk = &gpt7_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT7_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt7_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT8_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT8_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt8_ick;
-
-static struct clk_hw_omap gpt8_ick_hw = {
- .hw = {
- .clk = &gpt8_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT8_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt8_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "per_clkdm", omap343x_gpt_clksel,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_GPT9_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_GPT9_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk gpt9_ick;
-
-static struct clk_hw_omap gpt9_ick_hw = {
- .hw = {
- .clk = &gpt9_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_GPT9_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt9_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk hdq_fck;
-
-static const char *hdq_fck_parent_names[] = {
- "core_12m_fck",
-};
-
-static struct clk_hw_omap hdq_fck_hw = {
- .hw = {
- .clk = &hdq_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_fck, hdq_fck_parent_names, aes2_ick_ops);
-
-static struct clk hdq_ick;
-
-static struct clk_hw_omap hdq_ick_hw = {
- .hw = {
- .clk = &hdq_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk hecc_ck;
-
-static struct clk_hw_omap hecc_ck_hw = {
- .hw = {
- .clk = &hecc_ck,
- },
- .ops = &clkhwops_am35xx_ipss_module_wait,
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_HECC_VBUSP_CLK_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hecc_ck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk hsotgusb_fck_am35xx;
-
-static struct clk_hw_omap hsotgusb_fck_am35xx_hw = {
- .hw = {
- .clk = &hsotgusb_fck_am35xx,
- },
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_USBOTG_FCLK_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hsotgusb_fck_am35xx, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk hsotgusb_ick_3430es1;
-
-static struct clk_hw_omap hsotgusb_ick_3430es1_hw = {
- .hw = {
- .clk = &hsotgusb_ick_3430es1,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hsotgusb_ick_3430es1, ipss_ick_parent_names, aes2_ick_ops);
-
-static struct clk hsotgusb_ick_3430es2;
-
-static struct clk_hw_omap hsotgusb_ick_3430es2_hw = {
- .hw = {
- .clk = &hsotgusb_ick_3430es2,
- },
- .ops = &clkhwops_omap3430es2_iclk_hsotgusb_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hsotgusb_ick_3430es2, ipss_ick_parent_names, aes2_ick_ops);
-
-static struct clk hsotgusb_ick_am35xx;
-
-static struct clk_hw_omap hsotgusb_ick_am35xx_hw = {
- .hw = {
- .clk = &hsotgusb_ick_am35xx,
- },
- .ops = &clkhwops_am35xx_ipss_module_wait,
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_USBOTG_VBUSP_CLK_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hsotgusb_ick_am35xx, emac_ick_parent_names, aes2_ick_ops);
-
-static struct clk i2c1_fck;
-
-static struct clk_hw_omap i2c1_fck_hw = {
- .hw = {
- .clk = &i2c1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk i2c1_ick;
-
-static struct clk_hw_omap i2c1_ick_hw = {
- .hw = {
- .clk = &i2c1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk i2c2_fck;
-
-static struct clk_hw_omap i2c2_fck_hw = {
- .hw = {
- .clk = &i2c2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk i2c2_ick;
-
-static struct clk_hw_omap i2c2_ick_hw = {
- .hw = {
- .clk = &i2c2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk i2c3_fck;
-
-static struct clk_hw_omap i2c3_fck_hw = {
- .hw = {
- .clk = &i2c3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_I2C3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c3_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk i2c3_ick;
-
-static struct clk_hw_omap i2c3_ick_hw = {
- .hw = {
- .clk = &i2c3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_I2C3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c3_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk icr_ick;
-
-static struct clk_hw_omap icr_ick_hw = {
- .hw = {
- .clk = &icr_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_ICR_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(icr_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk iva2_ck;
-
-static const char *iva2_ck_parent_names[] = {
- "dpll2_m2_ck",
-};
-
-static struct clk_hw_omap iva2_ck_hw = {
- .hw = {
- .clk = &iva2_ck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
- .clkdm_name = "iva2_clkdm",
-};
-
-DEFINE_STRUCT_CLK(iva2_ck, iva2_ck_parent_names, aes2_ick_ops);
-
-static struct clk mad2d_ick;
-
-static struct clk_hw_omap mad2d_ick_hw = {
- .hw = {
- .clk = &mad2d_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP3430_EN_MAD2D_SHIFT,
- .clkdm_name = "d2d_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mad2d_ick, core_l3_ick_parent_names, aes2_ick_ops);
-
-static struct clk mailboxes_ick;
-
-static struct clk_hw_omap mailboxes_ick_hw = {
- .hw = {
- .clk = &mailboxes_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mailboxes_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel mcbsp_15_clksel[] = {
- { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL },
-};
-
-static const char *mcbsp1_fck_parent_names[] = {
- "core_96m_fck", "mcbsp_clks",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_15_clksel,
- OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- OMAP2_MCBSP1_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP3430_EN_MCBSP1_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk mcbsp1_ick;
-
-static struct clk_hw_omap mcbsp1_ick_hw = {
- .hw = {
- .clk = &mcbsp1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp1_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk per_96m_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(per_96m_fck, "per_clkdm");
-DEFINE_STRUCT_CLK(per_96m_fck, cm_96m_fck_parent_names, core_l4_ick_ops);
-
-static const struct clksel mcbsp_234_clksel[] = {
- { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL },
-};
-
-static const char *mcbsp2_fck_parent_names[] = {
- "per_96m_fck", "mcbsp_clks",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "per_clkdm", mcbsp_234_clksel,
- OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- OMAP2_MCBSP2_CLKS_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_MCBSP2_SHIFT, &clkhwops_wait,
- mcbsp2_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk mcbsp2_ick;
-
-static struct clk_hw_omap mcbsp2_ick_hw = {
- .hw = {
- .clk = &mcbsp2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp2_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "per_clkdm", mcbsp_234_clksel,
- OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
- OMAP2_MCBSP3_CLKS_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_MCBSP3_SHIFT, &clkhwops_wait,
- mcbsp2_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk mcbsp3_ick;
-
-static struct clk_hw_omap mcbsp3_ick_hw = {
- .hw = {
- .clk = &mcbsp3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp3_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "per_clkdm", mcbsp_234_clksel,
- OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
- OMAP2_MCBSP4_CLKS_MASK,
- OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- OMAP3430_EN_MCBSP4_SHIFT, &clkhwops_wait,
- mcbsp2_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk mcbsp4_ick;
-
-static struct clk_hw_omap mcbsp4_ick_hw = {
- .hw = {
- .clk = &mcbsp4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp4_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_15_clksel,
- OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
- OMAP2_MCBSP5_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP3430_EN_MCBSP5_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, clkout2_src_ck_ops);
-
-static struct clk mcbsp5_ick;
-
-static struct clk_hw_omap mcbsp5_ick_hw = {
- .hw = {
- .clk = &mcbsp5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp5_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mcspi1_fck;
-
-static struct clk_hw_omap mcspi1_fck_hw = {
- .hw = {
- .clk = &mcspi1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk mcspi1_ick;
-
-static struct clk_hw_omap mcspi1_ick_hw = {
- .hw = {
- .clk = &mcspi1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mcspi2_fck;
-
-static struct clk_hw_omap mcspi2_fck_hw = {
- .hw = {
- .clk = &mcspi2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk mcspi2_ick;
-
-static struct clk_hw_omap mcspi2_ick_hw = {
- .hw = {
- .clk = &mcspi2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mcspi3_fck;
-
-static struct clk_hw_omap mcspi3_fck_hw = {
- .hw = {
- .clk = &mcspi3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi3_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk mcspi3_ick;
-
-static struct clk_hw_omap mcspi3_ick_hw = {
- .hw = {
- .clk = &mcspi3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi3_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mcspi4_fck;
-
-static struct clk_hw_omap mcspi4_fck_hw = {
- .hw = {
- .clk = &mcspi4_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi4_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk mcspi4_ick;
-
-static struct clk_hw_omap mcspi4_ick_hw = {
- .hw = {
- .clk = &mcspi4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi4_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mmchs1_fck;
-
-static struct clk_hw_omap mmchs1_fck_hw = {
- .hw = {
- .clk = &mmchs1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MMC1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs1_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk mmchs1_ick;
-
-static struct clk_hw_omap mmchs1_ick_hw = {
- .hw = {
- .clk = &mmchs1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MMC1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs1_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mmchs2_fck;
-
-static struct clk_hw_omap mmchs2_fck_hw = {
- .hw = {
- .clk = &mmchs2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MMC2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs2_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk mmchs2_ick;
-
-static struct clk_hw_omap mmchs2_ick_hw = {
- .hw = {
- .clk = &mmchs2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MMC2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs2_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk mmchs3_fck;
-
-static struct clk_hw_omap mmchs3_fck_hw = {
- .hw = {
- .clk = &mmchs3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs3_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk mmchs3_ick;
-
-static struct clk_hw_omap mmchs3_ick_hw = {
- .hw = {
- .clk = &mmchs3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs3_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk modem_fck;
-
-static struct clk_hw_omap modem_fck_hw = {
- .hw = {
- .clk = &modem_fck,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MODEM_SHIFT,
- .clkdm_name = "d2d_clkdm",
-};
-
-DEFINE_STRUCT_CLK(modem_fck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk mspro_fck;
-
-static struct clk_hw_omap mspro_fck_hw = {
- .hw = {
- .clk = &mspro_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_fck, csi2_96m_fck_parent_names, aes2_ick_ops);
-
-static struct clk mspro_ick;
-
-static struct clk_hw_omap mspro_ick_hw = {
- .hw = {
- .clk = &mspro_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk omap_192m_alwon_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(omap_192m_alwon_fck, NULL);
-DEFINE_STRUCT_CLK(omap_192m_alwon_fck, omap_96m_alwon_fck_parent_names,
- core_ck_ops);
-
-static struct clk omap_32ksync_ick;
-
-static struct clk_hw_omap omap_32ksync_ick_hw = {
- .hw = {
- .clk = &omap_32ksync_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_32KSYNC_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(omap_32ksync_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-static const struct clksel_rate omap_96m_alwon_fck_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_36XX },
- { .div = 2, .val = 2, .flags = RATE_IN_36XX },
- { .div = 0 }
-};
-
-static const struct clksel omap_96m_alwon_fck_clksel[] = {
- { .parent = &omap_192m_alwon_fck, .rates = omap_96m_alwon_fck_rates },
- { .parent = NULL }
-};
-
-static struct clk omap_96m_alwon_fck_3630;
-
-static const char *omap_96m_alwon_fck_3630_parent_names[] = {
- "omap_192m_alwon_fck",
-};
-
-static const struct clk_ops omap_96m_alwon_fck_3630_ops = {
- .set_rate = &omap2_clksel_set_rate,
- .recalc_rate = &omap2_clksel_recalc,
- .round_rate = &omap2_clksel_round_rate,
-};
-
-static struct clk_hw_omap omap_96m_alwon_fck_3630_hw = {
- .hw = {
- .clk = &omap_96m_alwon_fck_3630,
- },
- .clksel = omap_96m_alwon_fck_clksel,
- .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3630_CLKSEL_96M_MASK,
-};
-
-static struct clk omap_96m_alwon_fck_3630 = {
- .name = "omap_96m_alwon_fck",
- .hw = &omap_96m_alwon_fck_3630_hw.hw,
- .parent_names = omap_96m_alwon_fck_3630_parent_names,
- .num_parents = ARRAY_SIZE(omap_96m_alwon_fck_3630_parent_names),
- .ops = &omap_96m_alwon_fck_3630_ops,
-};
-
-static struct clk omapctrl_ick;
-
-static struct clk_hw_omap omapctrl_ick_hw = {
- .hw = {
- .clk = &omapctrl_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(omapctrl_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_CLKSEL_PCLK_SHIFT, OMAP3430_CLKSEL_PCLK_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_CLKSEL_PCLKX2_SHIFT, OMAP3430_CLKSEL_PCLKX2_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk per_48m_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(per_48m_fck, "per_clkdm");
-DEFINE_STRUCT_CLK(per_48m_fck, core_48m_fck_parent_names, core_l4_ick_ops);
-
-static struct clk security_l3_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(security_l3_ick, NULL);
-DEFINE_STRUCT_CLK(security_l3_ick, core_l3_ick_parent_names, core_ck_ops);
-
-static struct clk pka_ick;
-
-static const char *pka_ick_parent_names[] = {
- "security_l3_ick",
-};
-
-static struct clk_hw_omap pka_ick_hw = {
- .hw = {
- .clk = &pka_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_PKA_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(pka_ick, pka_ick_parent_names, aes1_ick_ops);
-
-DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick, 0x0,
- OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_RM_SHIFT, OMAP3430_CLKSEL_RM_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk rng_ick;
-
-static struct clk_hw_omap rng_ick_hw = {
- .hw = {
- .clk = &rng_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_RNG_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(rng_ick, aes1_ick_parent_names, aes1_ick_ops);
-
-static struct clk sad2d_ick;
-
-static struct clk_hw_omap sad2d_ick_hw = {
- .hw = {
- .clk = &sad2d_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SAD2D_SHIFT,
- .clkdm_name = "d2d_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sad2d_ick, core_l3_ick_parent_names, aes2_ick_ops);
-
-static struct clk sdrc_ick;
-
-static struct clk_hw_omap sdrc_ick_hw = {
- .hw = {
- .clk = &sdrc_ick,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SDRC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdrc_ick, ipss_ick_parent_names, aes2_ick_ops);
-
-static const struct clksel_rate sgx_core_rates[] = {
- { .div = 2, .val = 5, .flags = RATE_IN_36XX },
- { .div = 3, .val = 0, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate sgx_96m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate sgx_192m_rates[] = {
- { .div = 1, .val = 4, .flags = RATE_IN_36XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate sgx_corex2_rates[] = {
- { .div = 3, .val = 6, .flags = RATE_IN_36XX },
- { .div = 5, .val = 7, .flags = RATE_IN_36XX },
- { .div = 0 }
-};
-
-static const struct clksel sgx_clksel[] = {
- { .parent = &core_ck, .rates = sgx_core_rates },
- { .parent = &cm_96m_fck, .rates = sgx_96m_rates },
- { .parent = &omap_192m_alwon_fck, .rates = sgx_192m_rates },
- { .parent = &corex2_fck, .rates = sgx_corex2_rates },
- { .parent = NULL },
-};
-
-static const char *sgx_fck_parent_names[] = {
- "core_ck", "cm_96m_fck", "omap_192m_alwon_fck", "corex2_fck",
-};
-
-static struct clk sgx_fck;
-
-static const struct clk_ops sgx_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(sgx_fck, "sgx_clkdm", sgx_clksel,
- OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
- OMAP3430ES2_CLKSEL_SGX_MASK,
- OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
- OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT,
- &clkhwops_wait, sgx_fck_parent_names, sgx_fck_ops);
-
-static struct clk sgx_ick;
-
-static struct clk_hw_omap sgx_ick_hw = {
- .hw = {
- .clk = &sgx_ick,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT,
- .clkdm_name = "sgx_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sgx_ick, core_l3_ick_parent_names, aes2_ick_ops);
-
-static struct clk sha11_ick;
-
-static struct clk_hw_omap sha11_ick_hw = {
- .hw = {
- .clk = &sha11_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP3430_EN_SHA11_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(sha11_ick, aes1_ick_parent_names, aes1_ick_ops);
-
-static struct clk sha12_ick;
-
-static struct clk_hw_omap sha12_ick_hw = {
- .hw = {
- .clk = &sha12_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SHA12_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sha12_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk sr1_fck;
-
-static struct clk_hw_omap sr1_fck_hw = {
- .hw = {
- .clk = &sr1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_SR1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sr1_fck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk sr2_fck;
-
-static struct clk_hw_omap sr2_fck_hw = {
- .hw = {
- .clk = &sr2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_SR2_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sr2_fck, cpefuse_fck_parent_names, aes2_ick_ops);
-
-static struct clk sr_l4_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(sr_l4_ick, "core_l4_clkdm");
-DEFINE_STRUCT_CLK(sr_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
-
-static struct clk ssi_l4_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(ssi_l4_ick, "core_l4_clkdm");
-DEFINE_STRUCT_CLK(ssi_l4_ick, security_l4_ick2_parent_names, core_l4_ick_ops);
-
-static struct clk ssi_ick_3430es1;
-
-static const char *ssi_ick_3430es1_parent_names[] = {
- "ssi_l4_ick",
-};
-
-static struct clk_hw_omap ssi_ick_3430es1_hw = {
- .hw = {
- .clk = &ssi_ick_3430es1,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SSI_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ssi_ick_3430es1, ssi_ick_3430es1_parent_names, aes2_ick_ops);
-
-static struct clk ssi_ick_3430es2;
-
-static struct clk_hw_omap ssi_ick_3430es2_hw = {
- .hw = {
- .clk = &ssi_ick_3430es2,
- },
- .ops = &clkhwops_omap3430es2_iclk_ssi_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_SSI_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ssi_ick_3430es2, ssi_ick_3430es1_parent_names, aes2_ick_ops);
-
-static const struct clksel_rate ssi_ssr_corex2_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 3, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 6, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel ssi_ssr_clksel[] = {
- { .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
- { .parent = NULL },
-};
-
-static const char *ssi_ssr_fck_3430es1_parent_names[] = {
- "corex2_fck",
-};
-
-static const struct clk_ops ssi_ssr_fck_3430es1_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es1, "core_l4_clkdm",
- ssi_ssr_clksel, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_SSI_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP3430_EN_SSI_SHIFT,
- NULL, ssi_ssr_fck_3430es1_parent_names,
- ssi_ssr_fck_3430es1_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es2, "core_l4_clkdm",
- ssi_ssr_clksel, OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430_CLKSEL_SSI_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP3430_EN_SSI_SHIFT,
- NULL, ssi_ssr_fck_3430es1_parent_names,
- ssi_ssr_fck_3430es1_ops);
-
-DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es1, "ssi_ssr_fck_3430es1",
- &ssi_ssr_fck_3430es1, 0x0, 1, 2);
-
-DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es2, "ssi_ssr_fck_3430es2",
- &ssi_ssr_fck_3430es2, 0x0, 1, 2);
-
-static struct clk sys_clkout1;
-
-static const char *sys_clkout1_parent_names[] = {
- "osc_sys_ck",
-};
-
-static struct clk_hw_omap sys_clkout1_hw = {
- .hw = {
- .clk = &sys_clkout1,
- },
- .enable_reg = OMAP3430_PRM_CLKOUT_CTRL,
- .enable_bit = OMAP3430_CLKOUT_EN_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(sys_clkout1, sys_clkout1_parent_names, aes1_ick_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck, 0x0,
- OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_DIV_SHIFT,
- OMAP3430_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_MUX(traceclk_src_fck, emu_src_ck_parent_names, NULL, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_TRACE_MUX_CTRL_SHIFT, OMAP3430_TRACE_MUX_CTRL_WIDTH,
- 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck, 0x0,
- OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- OMAP3430_CLKSEL_TRACECLK_SHIFT,
- OMAP3430_CLKSEL_TRACECLK_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk ts_fck;
-
-static struct clk_hw_omap ts_fck_hw = {
- .hw = {
- .clk = &ts_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
- .enable_bit = OMAP3430ES2_EN_TS_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ts_fck, wkup_32k_fck_parent_names, aes2_ick_ops);
-
-static struct clk uart1_fck;
-
-static struct clk_hw_omap uart1_fck_hw = {
- .hw = {
- .clk = &uart1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk uart1_ick;
-
-static struct clk_hw_omap uart1_ick_hw = {
- .hw = {
- .clk = &uart1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk uart2_fck;
-
-static struct clk_hw_omap uart2_fck_hw = {
- .hw = {
- .clk = &uart2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP3430_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_fck, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk uart2_ick;
-
-static struct clk_hw_omap uart2_ick_hw = {
- .hw = {
- .clk = &uart2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP3430_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static struct clk uart3_fck;
-
-static const char *uart3_fck_parent_names[] = {
- "per_48m_fck",
-};
-
-static struct clk_hw_omap uart3_fck_hw = {
- .hw = {
- .clk = &uart3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_UART3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_fck, uart3_fck_parent_names, aes2_ick_ops);
-
-static struct clk uart3_ick;
-
-static struct clk_hw_omap uart3_ick_hw = {
- .hw = {
- .clk = &uart3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_UART3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk uart4_fck;
-
-static struct clk_hw_omap uart4_fck_hw = {
- .hw = {
- .clk = &uart4_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3630_EN_UART4_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart4_fck, uart3_fck_parent_names, aes2_ick_ops);
-
-static struct clk uart4_fck_am35xx;
-
-static struct clk_hw_omap uart4_fck_am35xx_hw = {
- .hw = {
- .clk = &uart4_fck_am35xx,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = AM35XX_EN_UART4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart4_fck_am35xx, fshostusb_fck_parent_names, aes2_ick_ops);
-
-static struct clk uart4_ick;
-
-static struct clk_hw_omap uart4_ick_hw = {
- .hw = {
- .clk = &uart4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3630_EN_UART4_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart4_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-static struct clk uart4_ick_am35xx;
-
-static struct clk_hw_omap uart4_ick_am35xx_hw = {
- .hw = {
- .clk = &uart4_ick_am35xx,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = AM35XX_EN_UART4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart4_ick_am35xx, aes2_ick_parent_names, aes2_ick_ops);
-
-static const struct clksel_rate div2_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_3XXX },
- { .div = 2, .val = 2, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel usb_l4_clksel[] = {
- { .parent = &l4_ick, .rates = div2_rates },
- { .parent = NULL },
-};
-
-static const char *usb_l4_ick_parent_names[] = {
- "l4_ick",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
- OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
- &clkhwops_iclk_wait, usb_l4_ick_parent_names,
- ssi_ssr_fck_3430es1_ops);
-
-static struct clk usbhost_120m_fck;
-
-static const char *usbhost_120m_fck_parent_names[] = {
- "dpll5_m2_ck",
-};
-
-static struct clk_hw_omap usbhost_120m_fck_hw = {
- .hw = {
- .clk = &usbhost_120m_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT,
- .clkdm_name = "usbhost_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbhost_120m_fck, usbhost_120m_fck_parent_names,
- aes2_ick_ops);
-
-static struct clk usbhost_48m_fck;
-
-static struct clk_hw_omap usbhost_48m_fck_hw = {
- .hw = {
- .clk = &usbhost_48m_fck,
- },
- .ops = &clkhwops_omap3430es2_dss_usbhost_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT,
- .clkdm_name = "usbhost_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbhost_48m_fck, core_48m_fck_parent_names, aes2_ick_ops);
-
-static struct clk usbhost_ick;
-
-static struct clk_hw_omap usbhost_ick_hw = {
- .hw = {
- .clk = &usbhost_ick,
- },
- .ops = &clkhwops_omap3430es2_iclk_dss_usbhost_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT,
- .clkdm_name = "usbhost_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbhost_ick, security_l4_ick2_parent_names, aes2_ick_ops);
-
-static struct clk usbtll_fck;
-
-static struct clk_hw_omap usbtll_fck_hw = {
- .hw = {
- .clk = &usbtll_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
- .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbtll_fck, usbhost_120m_fck_parent_names, aes2_ick_ops);
-
-static struct clk usbtll_ick;
-
-static struct clk_hw_omap usbtll_ick_hw = {
- .hw = {
- .clk = &usbtll_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbtll_ick, aes2_ick_parent_names, aes2_ick_ops);
-
-static const struct clksel_rate usim_96m_rates[] = {
- { .div = 2, .val = 3, .flags = RATE_IN_3XXX },
- { .div = 4, .val = 4, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 5, .flags = RATE_IN_3XXX },
- { .div = 10, .val = 6, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel_rate usim_120m_rates[] = {
- { .div = 4, .val = 7, .flags = RATE_IN_3XXX },
- { .div = 8, .val = 8, .flags = RATE_IN_3XXX },
- { .div = 16, .val = 9, .flags = RATE_IN_3XXX },
- { .div = 20, .val = 10, .flags = RATE_IN_3XXX },
- { .div = 0 }
-};
-
-static const struct clksel usim_clksel[] = {
- { .parent = &omap_96m_fck, .rates = usim_96m_rates },
- { .parent = &dpll5_m2_ck, .rates = usim_120m_rates },
- { .parent = &sys_ck, .rates = div2_rates },
- { .parent = NULL },
-};
-
-static const char *usim_fck_parent_names[] = {
- "omap_96m_fck", "dpll5_m2_ck", "sys_ck",
-};
-
-static struct clk usim_fck;
-
-static const struct clk_ops usim_fck_ops = {
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(usim_fck, NULL, usim_clksel,
- OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
- OMAP3430ES2_CLKSEL_USIMOCP_MASK,
- OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- OMAP3430ES2_EN_USIMOCP_SHIFT, &clkhwops_wait,
- usim_fck_parent_names, usim_fck_ops);
-
-static struct clk usim_ick;
-
-static struct clk_hw_omap usim_ick_hw = {
- .hw = {
- .clk = &usim_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usim_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-static struct clk vpfe_fck;
-
-static const char *vpfe_fck_parent_names[] = {
- "pclk_ck",
-};
-
-static struct clk_hw_omap vpfe_fck_hw = {
- .hw = {
- .clk = &vpfe_fck,
- },
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_VPFE_FCLK_SHIFT,
-};
-
-DEFINE_STRUCT_CLK(vpfe_fck, vpfe_fck_parent_names, aes1_ick_ops);
-
-static struct clk vpfe_ick;
-
-static struct clk_hw_omap vpfe_ick_hw = {
- .hw = {
- .clk = &vpfe_ick,
- },
- .ops = &clkhwops_am35xx_ipss_module_wait,
- .enable_reg = OMAP343X_CTRL_REGADDR(AM35XX_CONTROL_IPSS_CLK_CTRL),
- .enable_bit = AM35XX_VPFE_VBUSP_CLK_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(vpfe_ick, emac_ick_parent_names, aes2_ick_ops);
-
-static struct clk wdt1_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(wdt1_fck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(wdt1_fck, gpt12_fck_parent_names, core_l4_ick_ops);
-
-static struct clk wdt1_ick;
-
-static struct clk_hw_omap wdt1_ick_hw = {
- .hw = {
- .clk = &wdt1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_WDT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt1_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-static struct clk wdt2_fck;
-
-static struct clk_hw_omap wdt2_fck_hw = {
- .hw = {
- .clk = &wdt2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_WDT2_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt2_fck, gpio1_dbck_parent_names, aes2_ick_ops);
-
-static struct clk wdt2_ick;
-
-static struct clk_hw_omap wdt2_ick_hw = {
- .hw = {
- .clk = &wdt2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_WDT2_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt2_ick, gpio1_ick_parent_names, aes2_ick_ops);
-
-static struct clk wdt3_fck;
-
-static struct clk_hw_omap wdt3_fck_hw = {
- .hw = {
- .clk = &wdt3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
- .enable_bit = OMAP3430_EN_WDT3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt3_fck, gpio2_dbck_parent_names, aes2_ick_ops);
-
-static struct clk wdt3_ick;
-
-static struct clk_hw_omap wdt3_ick_hw = {
- .hw = {
- .clk = &wdt3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
- .enable_bit = OMAP3430_EN_WDT3_SHIFT,
- .clkdm_name = "per_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt3_ick, gpio2_ick_parent_names, aes2_ick_ops);
-
-/*
- * clocks specific to omap3430es1
- */
-static struct omap_clk omap3430es1_clks[] = {
- CLK(NULL, "gfx_l3_ck", &gfx_l3_ck),
- CLK(NULL, "gfx_l3_fck", &gfx_l3_fck),
- CLK(NULL, "gfx_l3_ick", &gfx_l3_ick),
- CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck),
- CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck),
- CLK(NULL, "d2d_26m_fck", &d2d_26m_fck),
- CLK(NULL, "fshostusb_fck", &fshostusb_fck),
- CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1),
- CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1),
- CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es1),
- CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es1),
- CLK(NULL, "fac_ick", &fac_ick),
- CLK(NULL, "ssi_ick", &ssi_ick_3430es1),
- CLK(NULL, "usb_l4_ick", &usb_l4_ick),
- CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es1),
- CLK("omapdss_dss", "ick", &dss_ick_3430es1),
- CLK(NULL, "dss_ick", &dss_ick_3430es1),
-};
-
-/*
- * clocks specific to am35xx
- */
-static struct omap_clk am35xx_clks[] = {
- CLK(NULL, "ipss_ick", &ipss_ick),
- CLK(NULL, "rmii_ck", &rmii_ck),
- CLK(NULL, "pclk_ck", &pclk_ck),
- CLK(NULL, "emac_ick", &emac_ick),
- CLK(NULL, "emac_fck", &emac_fck),
- CLK("davinci_emac.0", NULL, &emac_ick),
- CLK("davinci_mdio.0", NULL, &emac_fck),
- CLK("vpfe-capture", "master", &vpfe_ick),
- CLK("vpfe-capture", "slave", &vpfe_fck),
- CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_am35xx),
- CLK(NULL, "hsotgusb_fck", &hsotgusb_fck_am35xx),
- CLK(NULL, "hecc_ck", &hecc_ck),
- CLK(NULL, "uart4_ick", &uart4_ick_am35xx),
- CLK(NULL, "uart4_fck", &uart4_fck_am35xx),
-};
-
-/*
- * clocks specific to omap36xx
- */
-static struct omap_clk omap36xx_clks[] = {
- CLK(NULL, "omap_192m_alwon_fck", &omap_192m_alwon_fck),
- CLK(NULL, "uart4_fck", &uart4_fck),
-};
-
-/*
- * clocks common to omap36xx omap34xx
- */
-static struct omap_clk omap34xx_omap36xx_clks[] = {
- CLK(NULL, "aes1_ick", &aes1_ick),
- CLK("omap_rng", "ick", &rng_ick),
- CLK("omap3-rom-rng", "ick", &rng_ick),
- CLK(NULL, "sha11_ick", &sha11_ick),
- CLK(NULL, "des1_ick", &des1_ick),
- CLK(NULL, "cam_mclk", &cam_mclk),
- CLK(NULL, "cam_ick", &cam_ick),
- CLK(NULL, "csi2_96m_fck", &csi2_96m_fck),
- CLK(NULL, "security_l3_ick", &security_l3_ick),
- CLK(NULL, "pka_ick", &pka_ick),
- CLK(NULL, "icr_ick", &icr_ick),
- CLK("omap-aes", "ick", &aes2_ick),
- CLK("omap-sham", "ick", &sha12_ick),
- CLK(NULL, "des2_ick", &des2_ick),
- CLK(NULL, "mspro_ick", &mspro_ick),
- CLK(NULL, "mailboxes_ick", &mailboxes_ick),
- CLK(NULL, "ssi_l4_ick", &ssi_l4_ick),
- CLK(NULL, "sr1_fck", &sr1_fck),
- CLK(NULL, "sr2_fck", &sr2_fck),
- CLK(NULL, "sr_l4_ick", &sr_l4_ick),
- CLK(NULL, "security_l4_ick2", &security_l4_ick2),
- CLK(NULL, "wkup_l4_ick", &wkup_l4_ick),
- CLK(NULL, "dpll2_fck", &dpll2_fck),
- CLK(NULL, "iva2_ck", &iva2_ck),
- CLK(NULL, "modem_fck", &modem_fck),
- CLK(NULL, "sad2d_ick", &sad2d_ick),
- CLK(NULL, "mad2d_ick", &mad2d_ick),
- CLK(NULL, "mspro_fck", &mspro_fck),
- CLK(NULL, "dpll2_ck", &dpll2_ck),
- CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck),
-};
-
-/*
- * clocks common to omap36xx and omap3430es2plus
- */
-static struct omap_clk omap36xx_omap3430es2plus_clks[] = {
- CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2),
- CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2),
- CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es2),
- CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es2),
- CLK(NULL, "ssi_ick", &ssi_ick_3430es2),
- CLK(NULL, "usim_fck", &usim_fck),
- CLK(NULL, "usim_ick", &usim_ick),
-};
-
-/*
- * clocks common to am35xx omap36xx and omap3430es2plus
- */
-static struct omap_clk omap36xx_am35xx_omap3430es2plus_clks[] = {
- CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck),
- CLK(NULL, "dpll5_ck", &dpll5_ck),
- CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck),
- CLK(NULL, "sgx_fck", &sgx_fck),
- CLK(NULL, "sgx_ick", &sgx_ick),
- CLK(NULL, "cpefuse_fck", &cpefuse_fck),
- CLK(NULL, "ts_fck", &ts_fck),
- CLK(NULL, "usbtll_fck", &usbtll_fck),
- CLK(NULL, "usbtll_ick", &usbtll_ick),
- CLK("omap_hsmmc.2", "ick", &mmchs3_ick),
- CLK(NULL, "mmchs3_ick", &mmchs3_ick),
- CLK(NULL, "mmchs3_fck", &mmchs3_fck),
- CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es2),
- CLK("omapdss_dss", "ick", &dss_ick_3430es2),
- CLK(NULL, "dss_ick", &dss_ick_3430es2),
- CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck),
- CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck),
- CLK(NULL, "usbhost_ick", &usbhost_ick),
-};
-
-/*
- * common clocks
- */
-static struct omap_clk omap3xxx_clks[] = {
- CLK(NULL, "apb_pclk", &dummy_apb_pclk),
- CLK(NULL, "omap_32k_fck", &omap_32k_fck),
- CLK(NULL, "virt_12m_ck", &virt_12m_ck),
- CLK(NULL, "virt_13m_ck", &virt_13m_ck),
- CLK(NULL, "virt_19200000_ck", &virt_19200000_ck),
- CLK(NULL, "virt_26000000_ck", &virt_26000000_ck),
- CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck),
- CLK(NULL, "osc_sys_ck", &osc_sys_ck),
- CLK("twl", "fck", &osc_sys_ck),
- CLK(NULL, "sys_ck", &sys_ck),
- CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck),
- CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck),
- CLK(NULL, "sys_altclk", &sys_altclk),
- CLK(NULL, "mcbsp_clks", &mcbsp_clks),
- CLK(NULL, "sys_clkout1", &sys_clkout1),
- CLK(NULL, "dpll1_ck", &dpll1_ck),
- CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck),
- CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck),
- CLK(NULL, "dpll3_ck", &dpll3_ck),
- CLK(NULL, "core_ck", &core_ck),
- CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck),
- CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck),
- CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck),
- CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck),
- CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck),
- CLK(NULL, "dpll4_ck", &dpll4_ck),
- CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck),
- CLK(NULL, "omap_96m_fck", &omap_96m_fck),
- CLK(NULL, "cm_96m_fck", &cm_96m_fck),
- CLK(NULL, "omap_54m_fck", &omap_54m_fck),
- CLK(NULL, "omap_48m_fck", &omap_48m_fck),
- CLK(NULL, "omap_12m_fck", &omap_12m_fck),
- CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck),
- CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck),
- CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck),
- CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck),
- CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck),
- CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck),
- CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck),
- CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck),
- CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck),
- CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck),
- CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck),
- CLK(NULL, "clkout2_src_ck", &clkout2_src_ck),
- CLK(NULL, "sys_clkout2", &sys_clkout2),
- CLK(NULL, "corex2_fck", &corex2_fck),
- CLK(NULL, "dpll1_fck", &dpll1_fck),
- CLK(NULL, "mpu_ck", &mpu_ck),
- CLK(NULL, "arm_fck", &arm_fck),
- CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck),
- CLK(NULL, "l3_ick", &l3_ick),
- CLK(NULL, "l4_ick", &l4_ick),
- CLK(NULL, "rm_ick", &rm_ick),
- CLK(NULL, "gpt10_fck", &gpt10_fck),
- CLK(NULL, "gpt11_fck", &gpt11_fck),
- CLK(NULL, "core_96m_fck", &core_96m_fck),
- CLK(NULL, "mmchs2_fck", &mmchs2_fck),
- CLK(NULL, "mmchs1_fck", &mmchs1_fck),
- CLK(NULL, "i2c3_fck", &i2c3_fck),
- CLK(NULL, "i2c2_fck", &i2c2_fck),
- CLK(NULL, "i2c1_fck", &i2c1_fck),
- CLK(NULL, "mcbsp5_fck", &mcbsp5_fck),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck),
- CLK(NULL, "core_48m_fck", &core_48m_fck),
- CLK(NULL, "mcspi4_fck", &mcspi4_fck),
- CLK(NULL, "mcspi3_fck", &mcspi3_fck),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck),
- CLK(NULL, "uart2_fck", &uart2_fck),
- CLK(NULL, "uart1_fck", &uart1_fck),
- CLK(NULL, "core_12m_fck", &core_12m_fck),
- CLK("omap_hdq.0", "fck", &hdq_fck),
- CLK(NULL, "hdq_fck", &hdq_fck),
- CLK(NULL, "core_l3_ick", &core_l3_ick),
- CLK(NULL, "sdrc_ick", &sdrc_ick),
- CLK(NULL, "gpmc_fck", &gpmc_fck),
- CLK(NULL, "core_l4_ick", &core_l4_ick),
- CLK("omap_hsmmc.1", "ick", &mmchs2_ick),
- CLK("omap_hsmmc.0", "ick", &mmchs1_ick),
- CLK(NULL, "mmchs2_ick", &mmchs2_ick),
- CLK(NULL, "mmchs1_ick", &mmchs1_ick),
- CLK("omap_hdq.0", "ick", &hdq_ick),
- CLK(NULL, "hdq_ick", &hdq_ick),
- CLK("omap2_mcspi.4", "ick", &mcspi4_ick),
- CLK("omap2_mcspi.3", "ick", &mcspi3_ick),
- CLK("omap2_mcspi.2", "ick", &mcspi2_ick),
- CLK("omap2_mcspi.1", "ick", &mcspi1_ick),
- CLK(NULL, "mcspi4_ick", &mcspi4_ick),
- CLK(NULL, "mcspi3_ick", &mcspi3_ick),
- CLK(NULL, "mcspi2_ick", &mcspi2_ick),
- CLK(NULL, "mcspi1_ick", &mcspi1_ick),
- CLK("omap_i2c.3", "ick", &i2c3_ick),
- CLK("omap_i2c.2", "ick", &i2c2_ick),
- CLK("omap_i2c.1", "ick", &i2c1_ick),
- CLK(NULL, "i2c3_ick", &i2c3_ick),
- CLK(NULL, "i2c2_ick", &i2c2_ick),
- CLK(NULL, "i2c1_ick", &i2c1_ick),
- CLK(NULL, "uart2_ick", &uart2_ick),
- CLK(NULL, "uart1_ick", &uart1_ick),
- CLK(NULL, "gpt11_ick", &gpt11_ick),
- CLK(NULL, "gpt10_ick", &gpt10_ick),
- CLK("omap-mcbsp.5", "ick", &mcbsp5_ick),
- CLK("omap-mcbsp.1", "ick", &mcbsp1_ick),
- CLK(NULL, "mcbsp5_ick", &mcbsp5_ick),
- CLK(NULL, "mcbsp1_ick", &mcbsp1_ick),
- CLK(NULL, "omapctrl_ick", &omapctrl_ick),
- CLK(NULL, "dss_tv_fck", &dss_tv_fck),
- CLK(NULL, "dss_96m_fck", &dss_96m_fck),
- CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck),
- CLK(NULL, "init_60m_fclk", &dummy_ck),
- CLK(NULL, "gpt1_fck", &gpt1_fck),
- CLK(NULL, "aes2_ick", &aes2_ick),
- CLK(NULL, "wkup_32k_fck", &wkup_32k_fck),
- CLK(NULL, "gpio1_dbck", &gpio1_dbck),
- CLK(NULL, "sha12_ick", &sha12_ick),
- CLK(NULL, "wdt2_fck", &wdt2_fck),
- CLK("omap_wdt", "ick", &wdt2_ick),
- CLK(NULL, "wdt2_ick", &wdt2_ick),
- CLK(NULL, "wdt1_ick", &wdt1_ick),
- CLK(NULL, "gpio1_ick", &gpio1_ick),
- CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick),
- CLK(NULL, "gpt12_ick", &gpt12_ick),
- CLK(NULL, "gpt1_ick", &gpt1_ick),
- CLK(NULL, "per_96m_fck", &per_96m_fck),
- CLK(NULL, "per_48m_fck", &per_48m_fck),
- CLK(NULL, "uart3_fck", &uart3_fck),
- CLK(NULL, "gpt2_fck", &gpt2_fck),
- CLK(NULL, "gpt3_fck", &gpt3_fck),
- CLK(NULL, "gpt4_fck", &gpt4_fck),
- CLK(NULL, "gpt5_fck", &gpt5_fck),
- CLK(NULL, "gpt6_fck", &gpt6_fck),
- CLK(NULL, "gpt7_fck", &gpt7_fck),
- CLK(NULL, "gpt8_fck", &gpt8_fck),
- CLK(NULL, "gpt9_fck", &gpt9_fck),
- CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck),
- CLK(NULL, "gpio6_dbck", &gpio6_dbck),
- CLK(NULL, "gpio5_dbck", &gpio5_dbck),
- CLK(NULL, "gpio4_dbck", &gpio4_dbck),
- CLK(NULL, "gpio3_dbck", &gpio3_dbck),
- CLK(NULL, "gpio2_dbck", &gpio2_dbck),
- CLK(NULL, "wdt3_fck", &wdt3_fck),
- CLK(NULL, "per_l4_ick", &per_l4_ick),
- CLK(NULL, "gpio6_ick", &gpio6_ick),
- CLK(NULL, "gpio5_ick", &gpio5_ick),
- CLK(NULL, "gpio4_ick", &gpio4_ick),
- CLK(NULL, "gpio3_ick", &gpio3_ick),
- CLK(NULL, "gpio2_ick", &gpio2_ick),
- CLK(NULL, "wdt3_ick", &wdt3_ick),
- CLK(NULL, "uart3_ick", &uart3_ick),
- CLK(NULL, "uart4_ick", &uart4_ick),
- CLK(NULL, "gpt9_ick", &gpt9_ick),
- CLK(NULL, "gpt8_ick", &gpt8_ick),
- CLK(NULL, "gpt7_ick", &gpt7_ick),
- CLK(NULL, "gpt6_ick", &gpt6_ick),
- CLK(NULL, "gpt5_ick", &gpt5_ick),
- CLK(NULL, "gpt4_ick", &gpt4_ick),
- CLK(NULL, "gpt3_ick", &gpt3_ick),
- CLK(NULL, "gpt2_ick", &gpt2_ick),
- CLK("omap-mcbsp.2", "ick", &mcbsp2_ick),
- CLK("omap-mcbsp.3", "ick", &mcbsp3_ick),
- CLK("omap-mcbsp.4", "ick", &mcbsp4_ick),
- CLK(NULL, "mcbsp4_ick", &mcbsp2_ick),
- CLK(NULL, "mcbsp3_ick", &mcbsp3_ick),
- CLK(NULL, "mcbsp2_ick", &mcbsp4_ick),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck),
- CLK(NULL, "mcbsp3_fck", &mcbsp3_fck),
- CLK(NULL, "mcbsp4_fck", &mcbsp4_fck),
- CLK("etb", "emu_src_ck", &emu_src_ck),
- CLK(NULL, "emu_src_ck", &emu_src_ck),
- CLK(NULL, "pclk_fck", &pclk_fck),
- CLK(NULL, "pclkx2_fck", &pclkx2_fck),
- CLK(NULL, "atclk_fck", &atclk_fck),
- CLK(NULL, "traceclk_src_fck", &traceclk_src_fck),
- CLK(NULL, "traceclk_fck", &traceclk_fck),
- CLK(NULL, "secure_32k_fck", &secure_32k_fck),
- CLK(NULL, "gpt12_fck", &gpt12_fck),
- CLK(NULL, "wdt1_fck", &wdt1_fck),
- CLK(NULL, "timer_32k_ck", &omap_32k_fck),
- CLK(NULL, "timer_sys_ck", &sys_ck),
- CLK(NULL, "cpufreq_ck", &dpll1_ck),
-};
-
-static const char *enable_init_clks[] = {
- "sdrc_ick",
- "gpmc_fck",
- "omapctrl_ick",
-};
-
-int __init omap3xxx_clk_init(void)
-{
- if (omap3_has_192mhz_clk())
- omap_96m_alwon_fck = omap_96m_alwon_fck_3630;
-
- if (cpu_is_omap3630()) {
- dpll3_m3x2_ck = dpll3_m3x2_ck_3630;
- dpll4_m2x2_ck = dpll4_m2x2_ck_3630;
- dpll4_m3x2_ck = dpll4_m3x2_ck_3630;
- dpll4_m4x2_ck = dpll4_m4x2_ck_3630;
- dpll4_m5x2_ck = dpll4_m5x2_ck_3630;
- dpll4_m6x2_ck = dpll4_m6x2_ck_3630;
- }
-
- /*
- * XXX This type of dynamic rewriting of the clock tree is
- * deprecated and should be revised soon.
- */
- if (cpu_is_omap3630())
- dpll4_dd = dpll4_dd_3630;
- else
- dpll4_dd = dpll4_dd_34xx;
-
-
- /*
- * 3505 must be tested before 3517, since 3517 returns true
- * for both AM3517 chips and AM3517 family chips, which
- * includes 3505. Unfortunately there's no obvious family
- * test for 3517/3505 :-(
- */
- if (soc_is_am35xx()) {
- cpu_mask = RATE_IN_34XX;
- omap_clocks_register(am35xx_clks, ARRAY_SIZE(am35xx_clks));
- omap_clocks_register(omap36xx_am35xx_omap3430es2plus_clks,
- ARRAY_SIZE(omap36xx_am35xx_omap3430es2plus_clks));
- omap_clocks_register(omap3xxx_clks, ARRAY_SIZE(omap3xxx_clks));
- } else if (cpu_is_omap3630()) {
- cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
- omap_clocks_register(omap36xx_clks, ARRAY_SIZE(omap36xx_clks));
- omap_clocks_register(omap36xx_omap3430es2plus_clks,
- ARRAY_SIZE(omap36xx_omap3430es2plus_clks));
- omap_clocks_register(omap34xx_omap36xx_clks,
- ARRAY_SIZE(omap34xx_omap36xx_clks));
- omap_clocks_register(omap36xx_am35xx_omap3430es2plus_clks,
- ARRAY_SIZE(omap36xx_am35xx_omap3430es2plus_clks));
- omap_clocks_register(omap3xxx_clks, ARRAY_SIZE(omap3xxx_clks));
- } else if (cpu_is_omap34xx()) {
- if (omap_rev() == OMAP3430_REV_ES1_0) {
- cpu_mask = RATE_IN_3430ES1;
- omap_clocks_register(omap3430es1_clks,
- ARRAY_SIZE(omap3430es1_clks));
- omap_clocks_register(omap34xx_omap36xx_clks,
- ARRAY_SIZE(omap34xx_omap36xx_clks));
- omap_clocks_register(omap3xxx_clks,
- ARRAY_SIZE(omap3xxx_clks));
- } else {
- /*
- * Assume that anything that we haven't matched yet
- * has 3430ES2-type clocks.
- */
- cpu_mask = RATE_IN_3430ES2PLUS;
- omap_clocks_register(omap34xx_omap36xx_clks,
- ARRAY_SIZE(omap34xx_omap36xx_clks));
- omap_clocks_register(omap36xx_omap3430es2plus_clks,
- ARRAY_SIZE(omap36xx_omap3430es2plus_clks));
- omap_clocks_register(omap36xx_am35xx_omap3430es2plus_clks,
- ARRAY_SIZE(omap36xx_am35xx_omap3430es2plus_clks));
- omap_clocks_register(omap3xxx_clks,
- ARRAY_SIZE(omap3xxx_clks));
- }
- } else {
- WARN(1, "clock: could not identify OMAP3 variant\n");
- }
-
- omap2_clk_disable_autoidle_all();
-
- omap2_clk_enable_init_clocks(enable_init_clks,
- ARRAY_SIZE(enable_init_clks));
-
- pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
- (clk_get_rate(&osc_sys_ck) / 1000000),
- (clk_get_rate(&osc_sys_ck) / 100000) % 10,
- (clk_get_rate(&core_ck) / 1000000),
- (clk_get_rate(&arm_fck) / 1000000));
-
- /*
- * Lock DPLL5 -- here only until other device init code can
- * handle this
- */
- if (omap_rev() >= OMAP3430_REV_ES2_0)
- omap3_clk_lock_dpll5();
-
- /* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
- sdrc_ick_p = clk_get(NULL, "sdrc_ick");
- arm_fck_p = clk_get(NULL, "arm_fck");
-
- return 0;
-}
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 4ae4ccebced285..6124db5c37aebf 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -23,7 +23,6 @@
#include
#include
#include
-#include
#include
#include
@@ -632,21 +631,6 @@ const struct clk_hw_omap_ops clkhwops_wait = {
.find_companion = omap2_clk_dflt_find_companion,
};
-/**
- * omap_clocks_register - register an array of omap_clk
- * @ocs: pointer to an array of omap_clk to register
- */
-void __init omap_clocks_register(struct omap_clk oclks[], int cnt)
-{
- struct omap_clk *c;
-
- for (c = oclks; c < oclks + cnt; c++) {
- clkdev_add(&c->lk);
- if (!__clk_init(NULL, c->lk.clk))
- omap2_init_clk_hw_omap_clocks(c->lk.clk);
- }
-}
-
/**
* omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
* @mpurate_ck_name: clk name of the clock to change rate
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 1cf9dd85248abb..a56742f96000a6 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -40,23 +40,29 @@ struct omap_clk {
struct clockdomain;
#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
- static struct clk _name = { \
+ static struct clk_core _name##_core = { \
.name = #_name, \
.hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \
+ }; \
+ static struct clk _name = { \
+ .core = &_name##_core, \
};
#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \
_clkops_name, _flags) \
- static struct clk _name = { \
+ static struct clk_core _name##_core = { \
.name = #_name, \
.hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \
.flags = _flags, \
+ }; \
+ static struct clk _name = { \
+ .core = &_name##_core, \
};
#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
@@ -238,7 +244,6 @@ struct ti_clk_features {
extern struct ti_clk_features ti_clk_features;
extern const struct clkops clkops_omap2_dflt_wait;
-extern const struct clkops clkops_dummy;
extern const struct clkops clkops_omap2_dflt;
extern struct clk_functions omap2_clk_functions;
@@ -247,7 +252,6 @@ extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
-extern struct clk dummy_ck;
extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
extern const struct clk_hw_omap_ops clkhwops_wait;
@@ -272,7 +276,5 @@ extern void __iomem *clk_memmaps[];
extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
-extern void omap_clocks_register(struct omap_clk *oclks, int cnt);
-
void __init ti_clk_init_features(void);
#endif
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index ef4d21bfb96478..61b60dfb14ce8a 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -16,7 +16,6 @@
* OMAP3xxx clock definition files.
*/
-#include
#include "clock.h"
/* clksel_rate data common to 24xx/343x */
@@ -114,13 +113,3 @@ const struct clksel_rate div31_1to31_rates[] = {
{ .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
{ .div = 0 },
};
-
-/* Clocks shared between various OMAP SoCs */
-
-static struct clk_ops dummy_ck_ops = {};
-
-struct clk dummy_ck = {
- .name = "dummy_clk",
- .ops = &dummy_ck_ops,
- .flags = CLK_IS_BASIC,
-};
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0fe5ad64..44e57ec225d440 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
int r;
struct dpll_data *dd;
- struct clk *parent;
+ struct clk_hw *parent;
dd = clk->dpll_data;
if (!dd)
@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
}
}
- parent = __clk_get_parent(hw->clk);
+ parent = __clk_get_hw(__clk_get_parent(hw->clk));
if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
- WARN_ON(parent != dd->clk_bypass);
+ WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
r = _omap3_noncore_dpll_bypass(clk);
} else {
- WARN_ON(parent != dd->clk_ref);
+ WARN_ON(parent != __clk_get_hw(dd->clk_ref));
r = _omap3_noncore_dpll_lock(clk);
}
@@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
* in failure.
*/
long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
@@ -549,7 +551,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
if (!dd)
return -EINVAL;
- if (__clk_get_parent(hw->clk) != dd->clk_ref)
+ if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+ __clk_get_hw(dd->clk_ref))
return -EINVAL;
if (dd->last_rounded_rate == 0)
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index fc712240e5fd9d..f231be05b9a638 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -202,6 +202,8 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
* in failure.
*/
long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index e60780f0537492..c4871c55bd8b64 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -461,7 +461,17 @@ void __init omap3_init_early(void)
omap3xxx_clockdomains_init();
omap3xxx_hwmod_init();
omap_hwmod_init_postsetup();
- omap_clk_soc_init = omap3xxx_clk_init;
+ if (!of_have_populated_dt()) {
+ omap3_prcm_legacy_iomaps_init();
+ if (soc_is_am35xx())
+ omap_clk_soc_init = am35xx_clk_legacy_init;
+ else if (cpu_is_omap3630())
+ omap_clk_soc_init = omap36xx_clk_legacy_init;
+ else if (omap_rev() == OMAP3430_REV_ES1_0)
+ omap_clk_soc_init = omap3430es1_clk_legacy_init;
+ else
+ omap_clk_soc_init = omap3430_clk_legacy_init;
+ }
}
void __init omap3430_init_early(void)
@@ -753,15 +763,17 @@ int __init omap_clk_init(void)
ti_clk_init_features();
- ret = of_prcm_init();
- if (ret)
- return ret;
+ if (of_have_populated_dt()) {
+ ret = of_prcm_init();
+ if (ret)
+ return ret;
- of_clk_init(NULL);
+ of_clk_init(NULL);
- ti_dt_clk_init_retry_clks();
+ ti_dt_clk_init_retry_clks();
- ti_dt_clockdomains_setup();
+ ti_dt_clockdomains_setup();
+ }
ret = omap_clk_soc_init();
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 77752e49d8d4c6..b9061a6a2db899 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -20,6 +20,7 @@ extern void __iomem *prm_base;
extern u16 prm_features;
extern void omap2_set_globals_prm(void __iomem *prm);
int of_prcm_init(void);
+void omap3_prcm_legacy_iomaps_init(void);
# endif
/*
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 264b5e29404d0e..bfaa7ba595cc83 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -35,6 +35,8 @@
#include "prm44xx.h"
#include "common.h"
#include "clock.h"
+#include "cm.h"
+#include "control.h"
/*
* OMAP_PRCM_MAX_NR_PENDING_REG: maximum number of PRM_IRQ*_MPU regs
@@ -641,6 +643,15 @@ int __init of_prcm_init(void)
return 0;
}
+void __init omap3_prcm_legacy_iomaps_init(void)
+{
+ ti_clk_ll_ops = &omap_clk_ll_ops;
+
+ clk_memmaps[TI_CLKM_CM] = cm_base + OMAP3430_IVA2_MOD;
+ clk_memmaps[TI_CLKM_PRM] = prm_base + OMAP3430_IVA2_MOD;
+ clk_memmaps[TI_CLKM_SCRM] = omap_ctrl_base_get();
+}
+
static int __init prm_late_init(void)
{
if (prm_ll_data->late_init)
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index ef016af1c9e769..914341bcef25fa 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -91,8 +91,6 @@ static void __init tegra_dt_init(void)
struct soc_device *soc_dev;
struct device *parent = NULL;
- tegra_clocks_apply_init_table();
-
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
goto out;
diff --git a/arch/blackfin/mach-bf527/boards/ad7160eval.c b/arch/blackfin/mach-bf527/boards/ad7160eval.c
index 9501bd8d9cd193..68f2a8a806ead4 100644
--- a/arch/blackfin/mach-bf527/boards/ad7160eval.c
+++ b/arch/blackfin/mach-bf527/boards/ad7160eval.c
@@ -666,7 +666,14 @@ static struct platform_device bfin_sport1_uart_device = {
#endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
-#include
+#include
+
+static const u16 per_cnt[] = {
+ P_CNT_CUD,
+ P_CNT_CDG,
+ P_CNT_CZM,
+ 0
+};
static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/
@@ -676,9 +683,15 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE,
.pm_wakeup = 1,
+ .pin_list = per_cnt,
};
static struct resource bfin_rotary_resources[] = {
+ {
+ .start = CNT_CONFIG,
+ .end = CNT_CONFIG + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = IRQ_CNT,
.end = IRQ_CNT,
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index d64f565dc2a0aa..d4219e8e5ab865 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -1092,7 +1092,14 @@ static struct platform_device bfin_device_gpiokeys = {
#endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
-#include
+#include
+
+static const u16 per_cnt[] = {
+ P_CNT_CUD,
+ P_CNT_CDG,
+ P_CNT_CZM,
+ 0
+};
static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/
@@ -1102,9 +1109,15 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
.debounce = 10, /* 0..17 */
.mode = ROT_QUAD_ENC | ROT_DEBE,
.pm_wakeup = 1,
+ .pin_list = per_cnt,
};
static struct resource bfin_rotary_resources[] = {
+ {
+ .start = CNT_CONFIG,
+ .end = CNT_CONFIG + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = IRQ_CNT,
.end = IRQ_CNT,
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 1fe7ff286619f6..4204b984253213 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -159,7 +159,7 @@ static struct platform_device bf54x_kpad_device = {
#endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
-#include
+#include
static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/
@@ -172,6 +172,11 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
};
static struct resource bfin_rotary_resources[] = {
+ {
+ .start = CNT_CONFIG,
+ .end = CNT_CONFIG + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = IRQ_CNT,
.end = IRQ_CNT,
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
index e2c0b024ce88f2..7f9fc272ec3057 100644
--- a/arch/blackfin/mach-bf609/boards/ezkit.c
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -75,7 +75,7 @@ static struct platform_device bfin_isp1760_device = {
#endif
#if IS_ENABLED(CONFIG_INPUT_BFIN_ROTARY)
-#include
+#include
static struct bfin_rotary_platform_data bfin_rotary_data = {
/*.rotary_up_key = KEY_UP,*/
@@ -87,6 +87,11 @@ static struct bfin_rotary_platform_data bfin_rotary_data = {
};
static struct resource bfin_rotary_resources[] = {
+ {
+ .start = CNT_CONFIG,
+ .end = CNT_CONFIG + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
{
.start = IRQ_CNT,
.end = IRQ_CNT,
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index 48a9dfc55b51aa..604b7d009d8d7f 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -546,6 +546,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
}
static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
@@ -678,6 +680,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
}
static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
@@ -897,6 +901,8 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
}
static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index 51866f17068457..ca7957b09a3cc1 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -142,6 +142,7 @@ CONFIG_VIRT_DRIVERS=y
CONFIG_FSL_HV_MANAGER=y
CONFIG_STAGING=y
CONFIG_FSL_CORENET_CF=y
+CONFIG_CLK_QORIQ=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index d6c0c819895288..04737aaa8b6b8e 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -122,6 +122,7 @@ CONFIG_DMADEVICES=y
CONFIG_FSL_DMA=y
CONFIG_VIRT_DRIVERS=y
CONFIG_FSL_HV_MANAGER=y
+CONFIG_CLK_QORIQ=y
CONFIG_FSL_CORENET_CF=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 7316dd15278a35..2d7b33fab95328 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -54,6 +54,7 @@
#include
#include
#include
+#include
#include
#include
@@ -975,6 +976,10 @@ void __init time_init(void)
init_decrementer_clockevent();
tick_setup_hrtimer_broadcast();
+
+#ifdef CONFIG_COMMON_CLK
+ of_clk_init(NULL);
+#endif
}
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 6eb614a271fbe0..f691bcabd71013 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -1168,6 +1168,11 @@ static void mpc5121_clk_provide_backwards_compat(void)
}
}
+/*
+ * The "fixed-clock" nodes (which includes the oscillator node if the board's
+ * DT provides one) has already been scanned by the of_clk_init() in
+ * time_init().
+ */
int __init mpc5121_clk_init(void)
{
struct device_node *clk_np;
@@ -1186,12 +1191,6 @@ int __init mpc5121_clk_init(void)
/* invalidate all not yet registered clock slots */
mpc512x_clk_preset_data();
- /*
- * have the device tree scanned for "fixed-clock" nodes (which
- * includes the oscillator node if the board's DT provides one)
- */
- of_clk_init(NULL);
-
/*
* add a dummy clock for those situations where a clock spec is
* required yet no real clock is involved
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index c4fbb9527c5ca2..b1453a2ae1ca58 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -18,15 +18,15 @@ struct cpu_topology_s390 {
cpumask_t book_mask;
};
-extern struct cpu_topology_s390 cpu_topology[NR_CPUS];
+DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);
-#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id)
-#define topology_thread_id(cpu) (cpu_topology[cpu].thread_id)
-#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_mask)
-#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
-#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_mask)
-#define topology_book_id(cpu) (cpu_topology[cpu].book_id)
-#define topology_book_cpumask(cpu) (&cpu_topology[cpu].book_mask)
+#define topology_physical_package_id(cpu) (per_cpu(cpu_topology, cpu).socket_id)
+#define topology_thread_id(cpu) (per_cpu(cpu_topology, cpu).thread_id)
+#define topology_thread_cpumask(cpu) (&per_cpu(cpu_topology, cpu).thread_mask)
+#define topology_core_id(cpu) (per_cpu(cpu_topology, cpu).core_id)
+#define topology_core_cpumask(cpu) (&per_cpu(cpu_topology, cpu).core_mask)
+#define topology_book_id(cpu) (per_cpu(cpu_topology, cpu).book_id)
+#define topology_book_cpumask(cpu) (&per_cpu(cpu_topology, cpu).book_mask)
#define mc_capable() 1
@@ -51,14 +51,6 @@ static inline void topology_expect_change(void) { }
#define POLARIZATION_VM (2)
#define POLARIZATION_VH (3)
-#ifdef CONFIG_SCHED_BOOK
-void s390_init_cpu_topology(void);
-#else
-static inline void s390_init_cpu_topology(void)
-{
-};
-#endif
-
#include
#endif /* _ASM_S390_TOPOLOGY_H */
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
index 632fa06ea162c5..0969d113b3d68f 100644
--- a/arch/s390/kernel/cache.c
+++ b/arch/s390/kernel/cache.c
@@ -91,12 +91,9 @@ static inline enum cache_type get_cache_type(struct cache_info *ci, int level)
{
if (level >= CACHE_MAX_LEVEL)
return CACHE_TYPE_NOCACHE;
-
ci += level;
-
if (ci->scope != CACHE_SCOPE_SHARED && ci->scope != CACHE_SCOPE_PRIVATE)
return CACHE_TYPE_NOCACHE;
-
return cache_type_map[ci->type];
}
@@ -111,23 +108,19 @@ static inline unsigned long ecag(int ai, int li, int ti)
}
static void ci_leaf_init(struct cacheinfo *this_leaf, int private,
- enum cache_type type, unsigned int level)
+ enum cache_type type, unsigned int level, int cpu)
{
int ti, num_sets;
- int cpu = smp_processor_id();
if (type == CACHE_TYPE_INST)
ti = CACHE_TI_INSTRUCTION;
else
ti = CACHE_TI_UNIFIED;
-
this_leaf->level = level + 1;
this_leaf->type = type;
this_leaf->coherency_line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
- this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY,
- level, ti);
+ this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
this_leaf->size = ecag(EXTRACT_SIZE, level, ti);
-
num_sets = this_leaf->size / this_leaf->coherency_line_size;
num_sets /= this_leaf->ways_of_associativity;
this_leaf->number_of_sets = num_sets;
@@ -145,7 +138,6 @@ int init_cache_level(unsigned int cpu)
if (!this_cpu_ci)
return -EINVAL;
-
ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
do {
ctype = get_cache_type(&ct.ci[0], level);
@@ -154,34 +146,31 @@ int init_cache_level(unsigned int cpu)
/* Separate instruction and data caches */
leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
} while (++level < CACHE_MAX_LEVEL);
-
this_cpu_ci->num_levels = level;
this_cpu_ci->num_leaves = leaves;
-
return 0;
}
int populate_cache_leaves(unsigned int cpu)
{
+ struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+ struct cacheinfo *this_leaf = this_cpu_ci->info_list;
unsigned int level, idx, pvt;
union cache_topology ct;
enum cache_type ctype;
- struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
- struct cacheinfo *this_leaf = this_cpu_ci->info_list;
ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
for (idx = 0, level = 0; level < this_cpu_ci->num_levels &&
idx < this_cpu_ci->num_leaves; idx++, level++) {
if (!this_leaf)
return -EINVAL;
-
pvt = (ct.ci[level].scope == CACHE_SCOPE_PRIVATE) ? 1 : 0;
ctype = get_cache_type(&ct.ci[0], level);
if (ctype == CACHE_TYPE_SEPARATE) {
- ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level);
- ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level);
+ ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level, cpu);
+ ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level, cpu);
} else {
- ci_leaf_init(this_leaf++, pvt, ctype, level);
+ ci_leaf_init(this_leaf++, pvt, ctype, level, cpu);
}
}
return 0;
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 70a3294509018e..4427ab7ac23af3 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -393,17 +393,19 @@ static __init void detect_machine_facilities(void)
S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
if (test_facility(129))
S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
- if (test_facility(128))
- S390_lowcore.machine_flags |= MACHINE_FLAG_CAD;
#endif
}
-static int __init nocad_setup(char *str)
+static int __init cad_setup(char *str)
{
- S390_lowcore.machine_flags &= ~MACHINE_FLAG_CAD;
+ int val;
+
+ get_option(&str, &val);
+ if (val && test_facility(128))
+ S390_lowcore.machine_flags |= MACHINE_FLAG_CAD;
return 0;
}
-early_param("nocad", nocad_setup);
+early_param("cad", cad_setup);
static int __init cad_init(void)
{
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index bfac77ada4f281..a5ea8bc17cb3bd 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -909,7 +909,6 @@ void __init setup_arch(char **cmdline_p)
setup_lowcore();
smp_fill_possible_mask();
cpu_init();
- s390_init_cpu_topology();
/*
* Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index a668993ff577f9..db8f1115a3bf55 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -59,14 +59,13 @@ enum {
CPU_STATE_CONFIGURED,
};
+static DEFINE_PER_CPU(struct cpu *, cpu_device);
+
struct pcpu {
- struct cpu *cpu;
struct _lowcore *lowcore; /* lowcore page(s) for the cpu */
- unsigned long async_stack; /* async stack for the cpu */
- unsigned long panic_stack; /* panic stack for the cpu */
unsigned long ec_mask; /* bit mask for ec_xxx functions */
- int state; /* physical cpu state */
- int polarization; /* physical polarization */
+ signed char state; /* physical cpu state */
+ signed char polarization; /* physical polarization */
u16 address; /* physical cpu address */
};
@@ -173,25 +172,30 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)
pcpu_sigp_retry(pcpu, order, 0);
}
+#define ASYNC_FRAME_OFFSET (ASYNC_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE)
+#define PANIC_FRAME_OFFSET (PAGE_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE)
+
static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
{
+ unsigned long async_stack, panic_stack;
struct _lowcore *lc;
if (pcpu != &pcpu_devices[0]) {
pcpu->lowcore = (struct _lowcore *)
__get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
- pcpu->async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
- pcpu->panic_stack = __get_free_page(GFP_KERNEL);
- if (!pcpu->lowcore || !pcpu->panic_stack || !pcpu->async_stack)
+ async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
+ panic_stack = __get_free_page(GFP_KERNEL);
+ if (!pcpu->lowcore || !panic_stack || !async_stack)
goto out;
+ } else {
+ async_stack = pcpu->lowcore->async_stack - ASYNC_FRAME_OFFSET;
+ panic_stack = pcpu->lowcore->panic_stack - PANIC_FRAME_OFFSET;
}
lc = pcpu->lowcore;
memcpy(lc, &S390_lowcore, 512);
memset((char *) lc + 512, 0, sizeof(*lc) - 512);
- lc->async_stack = pcpu->async_stack + ASYNC_SIZE
- - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
- lc->panic_stack = pcpu->panic_stack + PAGE_SIZE
- - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
+ lc->async_stack = async_stack + ASYNC_FRAME_OFFSET;
+ lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET;
lc->cpu_nr = cpu;
lc->spinlock_lockval = arch_spin_lockval(cpu);
#ifndef CONFIG_64BIT
@@ -212,8 +216,8 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
return 0;
out:
if (pcpu != &pcpu_devices[0]) {
- free_page(pcpu->panic_stack);
- free_pages(pcpu->async_stack, ASYNC_ORDER);
+ free_page(panic_stack);
+ free_pages(async_stack, ASYNC_ORDER);
free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
}
return -ENOMEM;
@@ -235,11 +239,11 @@ static void pcpu_free_lowcore(struct pcpu *pcpu)
#else
vdso_free_per_cpu(pcpu->lowcore);
#endif
- if (pcpu != &pcpu_devices[0]) {
- free_page(pcpu->panic_stack);
- free_pages(pcpu->async_stack, ASYNC_ORDER);
- free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
- }
+ if (pcpu == &pcpu_devices[0])
+ return;
+ free_page(pcpu->lowcore->panic_stack-PANIC_FRAME_OFFSET);
+ free_pages(pcpu->lowcore->async_stack-ASYNC_FRAME_OFFSET, ASYNC_ORDER);
+ free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
}
#endif /* CONFIG_HOTPLUG_CPU */
@@ -366,7 +370,8 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
void smp_call_ipl_cpu(void (*func)(void *), void *data)
{
pcpu_delegate(&pcpu_devices[0], func, data,
- pcpu_devices->panic_stack + PAGE_SIZE);
+ pcpu_devices->lowcore->panic_stack -
+ PANIC_FRAME_OFFSET + PAGE_SIZE);
}
int smp_find_processor_id(u16 address)
@@ -935,10 +940,6 @@ void __init smp_prepare_boot_cpu(void)
pcpu->state = CPU_STATE_CONFIGURED;
pcpu->address = stap();
pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix();
- pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE
- + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
- pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE
- + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
S390_lowcore.percpu_offset = __per_cpu_offset[0];
smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
set_cpu_present(0, true);
@@ -1078,8 +1079,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action,
void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
- struct cpu *c = pcpu_devices[cpu].cpu;
- struct device *s = &c->dev;
+ struct device *s = &per_cpu(cpu_device, cpu)->dev;
int err = 0;
switch (action & ~CPU_TASKS_FROZEN) {
@@ -1102,7 +1102,7 @@ static int smp_add_present_cpu(int cpu)
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
- pcpu_devices[cpu].cpu = c;
+ per_cpu(cpu_device, cpu) = c;
s = &c->dev;
c->hotpluggable = 1;
rc = register_cpu(c, cpu);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 24ee33f1af2422..14da43b801d93c 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -7,14 +7,14 @@
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include
-#include
#include
#include
#include
#include
#include
-#include
#include
+#include
+#include
#include
#include
#include
@@ -42,8 +42,8 @@ static DEFINE_SPINLOCK(topology_lock);
static struct mask_info socket_info;
static struct mask_info book_info;
-struct cpu_topology_s390 cpu_topology[NR_CPUS];
-EXPORT_SYMBOL_GPL(cpu_topology);
+DEFINE_PER_CPU(struct cpu_topology_s390, cpu_topology);
+EXPORT_PER_CPU_SYMBOL_GPL(cpu_topology);
static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
{
@@ -90,15 +90,15 @@ static struct mask_info *add_cpus_to_mask(struct topology_core *tl_core,
if (lcpu < 0)
continue;
for (i = 0; i <= smp_cpu_mtid; i++) {
- cpu_topology[lcpu + i].book_id = book->id;
- cpu_topology[lcpu + i].core_id = rcore;
- cpu_topology[lcpu + i].thread_id = lcpu + i;
+ per_cpu(cpu_topology, lcpu + i).book_id = book->id;
+ per_cpu(cpu_topology, lcpu + i).core_id = rcore;
+ per_cpu(cpu_topology, lcpu + i).thread_id = lcpu + i;
cpumask_set_cpu(lcpu + i, &book->mask);
cpumask_set_cpu(lcpu + i, &socket->mask);
if (one_socket_per_cpu)
- cpu_topology[lcpu + i].socket_id = rcore;
+ per_cpu(cpu_topology, lcpu + i).socket_id = rcore;
else
- cpu_topology[lcpu + i].socket_id = socket->id;
+ per_cpu(cpu_topology, lcpu + i).socket_id = socket->id;
smp_cpu_set_polarization(lcpu + i, tl_core->pp);
}
if (one_socket_per_cpu)
@@ -249,14 +249,14 @@ static void update_cpu_masks(void)
spin_lock_irqsave(&topology_lock, flags);
for_each_possible_cpu(cpu) {
- cpu_topology[cpu].thread_mask = cpu_thread_map(cpu);
- cpu_topology[cpu].core_mask = cpu_group_map(&socket_info, cpu);
- cpu_topology[cpu].book_mask = cpu_group_map(&book_info, cpu);
+ per_cpu(cpu_topology, cpu).thread_mask = cpu_thread_map(cpu);
+ per_cpu(cpu_topology, cpu).core_mask = cpu_group_map(&socket_info, cpu);
+ per_cpu(cpu_topology, cpu).book_mask = cpu_group_map(&book_info, cpu);
if (!MACHINE_HAS_TOPOLOGY) {
- cpu_topology[cpu].thread_id = cpu;
- cpu_topology[cpu].core_id = cpu;
- cpu_topology[cpu].socket_id = cpu;
- cpu_topology[cpu].book_id = cpu;
+ per_cpu(cpu_topology, cpu).thread_id = cpu;
+ per_cpu(cpu_topology, cpu).core_id = cpu;
+ per_cpu(cpu_topology, cpu).socket_id = cpu;
+ per_cpu(cpu_topology, cpu).book_id = cpu;
}
}
spin_unlock_irqrestore(&topology_lock, flags);
@@ -334,50 +334,6 @@ void topology_expect_change(void)
set_topology_timer();
}
-static int __init early_parse_topology(char *p)
-{
- if (strncmp(p, "off", 3))
- return 0;
- topology_enabled = 0;
- return 0;
-}
-early_param("topology", early_parse_topology);
-
-static void __init alloc_masks(struct sysinfo_15_1_x *info,
- struct mask_info *mask, int offset)
-{
- int i, nr_masks;
-
- nr_masks = info->mag[TOPOLOGY_NR_MAG - offset];
- for (i = 0; i < info->mnest - offset; i++)
- nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
- nr_masks = max(nr_masks, 1);
- for (i = 0; i < nr_masks; i++) {
- mask->next = alloc_bootmem_align(
- roundup_pow_of_two(sizeof(struct mask_info)),
- roundup_pow_of_two(sizeof(struct mask_info)));
- mask = mask->next;
- }
-}
-
-void __init s390_init_cpu_topology(void)
-{
- struct sysinfo_15_1_x *info;
- int i;
-
- if (!MACHINE_HAS_TOPOLOGY)
- return;
- tl_info = alloc_bootmem_pages(PAGE_SIZE);
- info = tl_info;
- store_topology(info);
- pr_info("The CPU configuration topology of the machine is:");
- for (i = 0; i < TOPOLOGY_NR_MAG; i++)
- printk(KERN_CONT " %d", info->mag[i]);
- printk(KERN_CONT " / %d\n", info->mnest);
- alloc_masks(info, &socket_info, 1);
- alloc_masks(info, &book_info, 2);
-}
-
static int cpu_management;
static ssize_t dispatching_show(struct device *dev,
@@ -467,20 +423,29 @@ int topology_cpu_init(struct cpu *cpu)
const struct cpumask *cpu_thread_mask(int cpu)
{
- return &cpu_topology[cpu].thread_mask;
+ return &per_cpu(cpu_topology, cpu).thread_mask;
}
const struct cpumask *cpu_coregroup_mask(int cpu)
{
- return &cpu_topology[cpu].core_mask;
+ return &per_cpu(cpu_topology, cpu).core_mask;
}
static const struct cpumask *cpu_book_mask(int cpu)
{
- return &cpu_topology[cpu].book_mask;
+ return &per_cpu(cpu_topology, cpu).book_mask;
}
+static int __init early_parse_topology(char *p)
+{
+ if (strncmp(p, "off", 3))
+ return 0;
+ topology_enabled = 0;
+ return 0;
+}
+early_param("topology", early_parse_topology);
+
static struct sched_domain_topology_level s390_topology[] = {
{ cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
@@ -489,6 +454,42 @@ static struct sched_domain_topology_level s390_topology[] = {
{ NULL, },
};
+static void __init alloc_masks(struct sysinfo_15_1_x *info,
+ struct mask_info *mask, int offset)
+{
+ int i, nr_masks;
+
+ nr_masks = info->mag[TOPOLOGY_NR_MAG - offset];
+ for (i = 0; i < info->mnest - offset; i++)
+ nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
+ nr_masks = max(nr_masks, 1);
+ for (i = 0; i < nr_masks; i++) {
+ mask->next = kzalloc(sizeof(*mask->next), GFP_KERNEL);
+ mask = mask->next;
+ }
+}
+
+static int __init s390_topology_init(void)
+{
+ struct sysinfo_15_1_x *info;
+ int i;
+
+ if (!MACHINE_HAS_TOPOLOGY)
+ return 0;
+ tl_info = (struct sysinfo_15_1_x *)__get_free_page(GFP_KERNEL);
+ info = tl_info;
+ store_topology(info);
+ pr_info("The CPU configuration topology of the machine is:");
+ for (i = 0; i < TOPOLOGY_NR_MAG; i++)
+ printk(KERN_CONT " %d", info->mag[i]);
+ printk(KERN_CONT " / %d\n", info->mnest);
+ alloc_masks(info, &socket_info, 1);
+ alloc_masks(info, &book_info, 2);
+ set_sched_topology(s390_topology);
+ return 0;
+}
+early_initcall(s390_topology_init);
+
static int __init topology_init(void)
{
if (MACHINE_HAS_TOPOLOGY)
@@ -498,10 +499,3 @@ static int __init topology_init(void)
return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
}
device_initcall(topology_init);
-
-static int __init early_topology_init(void)
-{
- set_sched_topology(s390_topology);
- return 0;
-}
-early_initcall(early_topology_init);
diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S
index 7699e735ae28ed..61541fb93dc63e 100644
--- a/arch/s390/kernel/vdso64/clock_gettime.S
+++ b/arch/s390/kernel/vdso64/clock_gettime.S
@@ -25,9 +25,7 @@ __kernel_clock_gettime:
je 4f
cghi %r2,__CLOCK_REALTIME
je 5f
- cghi %r2,__CLOCK_THREAD_CPUTIME_ID
- je 9f
- cghi %r2,-2 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
+ cghi %r2,-3 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
je 9f
cghi %r2,__CLOCK_MONOTONIC_COARSE
je 3f
@@ -106,7 +104,7 @@ __kernel_clock_gettime:
aghi %r15,16
br %r14
- /* CLOCK_THREAD_CPUTIME_ID for this thread */
+ /* CPUCLOCK_VIRT for this thread */
9: icm %r0,15,__VDSO_ECTG_OK(%r5)
jz 12f
ear %r2,%a4
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index d008f638b2cd27..179a2c20b01f14 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -183,7 +183,10 @@ unsigned long randomize_et_dyn(void)
{
unsigned long base;
- base = (STACK_TOP / 3 * 2) & (~mmap_align_mask << PAGE_SHIFT);
+ base = STACK_TOP / 3 * 2;
+ if (!is_32bit_task())
+ /* Align to 4GB */
+ base &= ~((1UL << 32) - 1);
return base + mmap_rnd();
}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index eb1cf898ed3cb5..c2fb8a87dccb29 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -488,6 +488,22 @@ config X86_INTEL_MID
Intel MID platforms are based on an Intel processor and chipset which
consume less power than most of the x86 derivatives.
+config X86_INTEL_QUARK
+ bool "Intel Quark platform support"
+ depends on X86_32
+ depends on X86_EXTENDED_PLATFORM
+ depends on X86_PLATFORM_DEVICES
+ depends on X86_TSC
+ depends on PCI
+ depends on PCI_GOANY
+ depends on X86_IO_APIC
+ select IOSF_MBI
+ select INTEL_IMR
+ ---help---
+ Select to include support for Quark X1000 SoC.
+ Say Y here if you have a Quark based system such as the Arduino
+ compatible Intel Galileo.
+
config X86_INTEL_LPSS
bool "Intel Low Power Subsystem Support"
depends on ACPI
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 61bd2ad9428188..20028da8ae188c 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -313,6 +313,19 @@ config DEBUG_NMI_SELFTEST
If unsure, say N.
+config DEBUG_IMR_SELFTEST
+ bool "Isolated Memory Region self test"
+ default n
+ depends on INTEL_IMR
+ ---help---
+ This option enables automated sanity testing of the IMR code.
+ Some simple tests are run to verify IMR bounds checking, alignment
+ and overlapping. This option is really only useful if you are
+ debugging an IMR memory map or are modifying the IMR code and want to
+ test your changes.
+
+ If unsure say N here.
+
config X86_DEBUG_STATIC_CPU_HAS
bool "Debug alternatives"
depends on DEBUG_KERNEL
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 843feb3eb20bd7..0a291cdfaf7710 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -51,6 +51,7 @@ $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
vmlinux-objs-$(CONFIG_EFI_STUB) += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
$(objtree)/drivers/firmware/efi/libstub/lib.a
+vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
$(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index bb1376381985ed..7083c16cccba0b 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -14,6 +14,13 @@
static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
+struct kaslr_setup_data {
+ __u64 next;
+ __u32 type;
+ __u32 len;
+ __u8 data[1];
+} kaslr_setup_data;
+
#define I8254_PORT_CONTROL 0x43
#define I8254_PORT_COUNTER0 0x40
#define I8254_CMD_READBACK 0xC0
@@ -295,7 +302,29 @@ static unsigned long find_random_addr(unsigned long minimum,
return slots_fetch_random();
}
-unsigned char *choose_kernel_location(unsigned char *input,
+static void add_kaslr_setup_data(struct boot_params *params, __u8 enabled)
+{
+ struct setup_data *data;
+
+ kaslr_setup_data.type = SETUP_KASLR;
+ kaslr_setup_data.len = 1;
+ kaslr_setup_data.next = 0;
+ kaslr_setup_data.data[0] = enabled;
+
+ data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
+
+ while (data && data->next)
+ data = (struct setup_data *)(unsigned long)data->next;
+
+ if (data)
+ data->next = (unsigned long)&kaslr_setup_data;
+ else
+ params->hdr.setup_data = (unsigned long)&kaslr_setup_data;
+
+}
+
+unsigned char *choose_kernel_location(struct boot_params *params,
+ unsigned char *input,
unsigned long input_size,
unsigned char *output,
unsigned long output_size)
@@ -306,14 +335,17 @@ unsigned char *choose_kernel_location(unsigned char *input,
#ifdef CONFIG_HIBERNATION
if (!cmdline_find_option_bool("kaslr")) {
debug_putstr("KASLR disabled by default...\n");
+ add_kaslr_setup_data(params, 0);
goto out;
}
#else
if (cmdline_find_option_bool("nokaslr")) {
debug_putstr("KASLR disabled by cmdline...\n");
+ add_kaslr_setup_data(params, 0);
goto out;
}
#endif
+ add_kaslr_setup_data(params, 1);
/* Record the various known unsafe memory ranges. */
mem_avoid_init((unsigned long)input, input_size,
diff --git a/arch/x86/boot/compressed/efi_stub_64.S b/arch/x86/boot/compressed/efi_stub_64.S
index 7ff3632806b18e..99494dff2113e5 100644
--- a/arch/x86/boot/compressed/efi_stub_64.S
+++ b/arch/x86/boot/compressed/efi_stub_64.S
@@ -3,28 +3,3 @@
#include
#include "../../platform/efi/efi_stub_64.S"
-
-#ifdef CONFIG_EFI_MIXED
- .code64
- .text
-ENTRY(efi64_thunk)
- push %rbp
- push %rbx
-
- subq $16, %rsp
- leaq efi_exit32(%rip), %rax
- movl %eax, 8(%rsp)
- leaq efi_gdt64(%rip), %rax
- movl %eax, 4(%rsp)
- movl %eax, 2(%rax) /* Fixup the gdt base address */
- leaq efi32_boot_gdt(%rip), %rax
- movl %eax, (%rsp)
-
- call __efi64_thunk
-
- addq $16, %rsp
- pop %rbx
- pop %rbp
- ret
-ENDPROC(efi64_thunk)
-#endif /* CONFIG_EFI_MIXED */
diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S
new file mode 100644
index 00000000000000..630384a4c14a96
--- /dev/null
+++ b/arch/x86/boot/compressed/efi_thunk_64.S
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
+ *
+ * Early support for invoking 32-bit EFI services from a 64-bit kernel.
+ *
+ * Because this thunking occurs before ExitBootServices() we have to
+ * restore the firmware's 32-bit GDT before we make EFI serivce calls,
+ * since the firmware's 32-bit IDT is still currently installed and it
+ * needs to be able to service interrupts.
+ *
+ * On the plus side, we don't have to worry about mangling 64-bit
+ * addresses into 32-bits because we're executing with an identify
+ * mapped pagetable and haven't transitioned to 64-bit virtual addresses
+ * yet.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+ .code64
+ .text
+ENTRY(efi64_thunk)
+ push %rbp
+ push %rbx
+
+ subq $8, %rsp
+ leaq efi_exit32(%rip), %rax
+ movl %eax, 4(%rsp)
+ leaq efi_gdt64(%rip), %rax
+ movl %eax, (%rsp)
+ movl %eax, 2(%rax) /* Fixup the gdt base address */
+
+ movl %ds, %eax
+ push %rax
+ movl %es, %eax
+ push %rax
+ movl %ss, %eax
+ push %rax
+
+ /*
+ * Convert x86-64 ABI params to i386 ABI
+ */
+ subq $32, %rsp
+ movl %esi, 0x0(%rsp)
+ movl %edx, 0x4(%rsp)
+ movl %ecx, 0x8(%rsp)
+ movq %r8, %rsi
+ movl %esi, 0xc(%rsp)
+ movq %r9, %rsi
+ movl %esi, 0x10(%rsp)
+
+ sgdt save_gdt(%rip)
+
+ leaq 1f(%rip), %rbx
+ movq %rbx, func_rt_ptr(%rip)
+
+ /*
+ * Switch to gdt with 32-bit segments. This is the firmware GDT
+ * that was installed when the kernel started executing. This
+ * pointer was saved at the EFI stub entry point in head_64.S.
+ */
+ leaq efi32_boot_gdt(%rip), %rax
+ lgdt (%rax)
+
+ pushq $__KERNEL_CS
+ leaq efi_enter32(%rip), %rax
+ pushq %rax
+ lretq
+
+1: addq $32, %rsp
+
+ lgdt save_gdt(%rip)
+
+ pop %rbx
+ movl %ebx, %ss
+ pop %rbx
+ movl %ebx, %es
+ pop %rbx
+ movl %ebx, %ds
+
+ /*
+ * Convert 32-bit status code into 64-bit.
+ */
+ test %rax, %rax
+ jz 1f
+ movl %eax, %ecx
+ andl $0x0fffffff, %ecx
+ andl $0xf0000000, %eax
+ shl $32, %rax
+ or %rcx, %rax
+1:
+ addq $8, %rsp
+ pop %rbx
+ pop %rbp
+ ret
+ENDPROC(efi64_thunk)
+
+ENTRY(efi_exit32)
+ movq func_rt_ptr(%rip), %rax
+ push %rax
+ mov %rdi, %rax
+ ret
+ENDPROC(efi_exit32)
+
+ .code32
+/*
+ * EFI service pointer must be in %edi.
+ *
+ * The stack should represent the 32-bit calling convention.
+ */
+ENTRY(efi_enter32)
+ movl $__KERNEL_DS, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+
+ /* Reload pgtables */
+ movl %cr3, %eax
+ movl %eax, %cr3
+
+ /* Disable paging */
+ movl %cr0, %eax
+ btrl $X86_CR0_PG_BIT, %eax
+ movl %eax, %cr0
+
+ /* Disable long mode via EFER */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btrl $_EFER_LME, %eax
+ wrmsr
+
+ call *%edi
+
+ /* We must preserve return value */
+ movl %eax, %edi
+
+ /*
+ * Some firmware will return with interrupts enabled. Be sure to
+ * disable them before we switch GDTs.
+ */
+ cli
+
+ movl 56(%esp), %eax
+ movl %eax, 2(%eax)
+ lgdtl (%eax)
+
+ movl %cr4, %eax
+ btsl $(X86_CR4_PAE_BIT), %eax
+ movl %eax, %cr4
+
+ movl %cr3, %eax
+ movl %eax, %cr3
+
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btsl $_EFER_LME, %eax
+ wrmsr
+
+ xorl %eax, %eax
+ lldt %ax
+
+ movl 60(%esp), %eax
+ pushl $__KERNEL_CS
+ pushl %eax
+
+ /* Enable paging */
+ movl %cr0, %eax
+ btsl $X86_CR0_PG_BIT, %eax
+ movl %eax, %cr0
+ lret
+ENDPROC(efi_enter32)
+
+ .data
+ .balign 8
+ .global efi32_boot_gdt
+efi32_boot_gdt: .word 0
+ .quad 0
+
+save_gdt: .word 0
+ .quad 0
+func_rt_ptr: .quad 0
+
+ .global efi_gdt64
+efi_gdt64:
+ .word efi_gdt64_end - efi_gdt64
+ .long 0 /* Filled out by user */
+ .word 0
+ .quad 0x0000000000000000 /* NULL descriptor */
+ .quad 0x00af9a000000ffff /* __KERNEL_CS */
+ .quad 0x00cf92000000ffff /* __KERNEL_DS */
+ .quad 0x0080890000000000 /* TS descriptor */
+ .quad 0x0000000000000000 /* TS continued */
+efi_gdt64_end:
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index a950864a64dab3..5903089c818f68 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -401,7 +401,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
* the entire decompressed kernel plus relocation table, or the
* entire decompressed kernel plus .bss and .brk sections.
*/
- output = choose_kernel_location(input_data, input_len, output,
+ output = choose_kernel_location(real_mode, input_data, input_len,
+ output,
output_len > run_size ? output_len
: run_size);
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 04477d68403f1f..ee3576b2666b81 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -57,7 +57,8 @@ int cmdline_find_option_bool(const char *option);
#if CONFIG_RANDOMIZE_BASE
/* aslr.c */
-unsigned char *choose_kernel_location(unsigned char *input,
+unsigned char *choose_kernel_location(struct boot_params *params,
+ unsigned char *input,
unsigned long input_size,
unsigned char *output,
unsigned long output_size);
@@ -65,7 +66,8 @@ unsigned char *choose_kernel_location(unsigned char *input,
bool has_cpuflag(int flag);
#else
static inline
-unsigned char *choose_kernel_location(unsigned char *input,
+unsigned char *choose_kernel_location(struct boot_params *params,
+ unsigned char *input,
unsigned long input_size,
unsigned char *output,
unsigned long output_size)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 92003f3c8a427b..efc3b22d896eb2 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -213,7 +213,15 @@ void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void);
extern int APIC_init_uniprocessor(void);
+
+#ifdef CONFIG_X86_64
+static inline int apic_force_enable(unsigned long addr)
+{
+ return -1;
+}
+#else
extern int apic_force_enable(unsigned long addr);
+#endif
extern int apic_bsp_setup(bool upmode);
extern void apic_ap_setup(void);
diff --git a/arch/x86/include/asm/imr.h b/arch/x86/include/asm/imr.h
new file mode 100644
index 00000000000000..cd2ce4068441b7
--- /dev/null
+++ b/arch/x86/include/asm/imr.h
@@ -0,0 +1,60 @@
+/*
+ * imr.h: Isolated Memory Region API
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2015 Bryan O'Donoghue
+ *
+ * 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; version 2
+ * of the License.
+ */
+#ifndef _IMR_H
+#define _IMR_H
+
+#include
+
+/*
+ * IMR agent access mask bits
+ * See section 12.7.4.7 from quark-x1000-datasheet.pdf for register
+ * definitions.
+ */
+#define IMR_ESRAM_FLUSH BIT(31)
+#define IMR_CPU_SNOOP BIT(30) /* Applicable only to write */
+#define IMR_RMU BIT(29)
+#define IMR_VC1_SAI_ID3 BIT(15)
+#define IMR_VC1_SAI_ID2 BIT(14)
+#define IMR_VC1_SAI_ID1 BIT(13)
+#define IMR_VC1_SAI_ID0 BIT(12)
+#define IMR_VC0_SAI_ID3 BIT(11)
+#define IMR_VC0_SAI_ID2 BIT(10)
+#define IMR_VC0_SAI_ID1 BIT(9)
+#define IMR_VC0_SAI_ID0 BIT(8)
+#define IMR_CPU_0 BIT(1) /* SMM mode */
+#define IMR_CPU BIT(0) /* Non SMM mode */
+#define IMR_ACCESS_NONE 0
+
+/*
+ * Read/Write access-all bits here include some reserved bits
+ * These are the values firmware uses and are accepted by hardware.
+ * The kernel defines read/write access-all in the same way as firmware
+ * in order to have a consistent and crisp definition across firmware,
+ * bootloader and kernel.
+ */
+#define IMR_READ_ACCESS_ALL 0xBFFFFFFF
+#define IMR_WRITE_ACCESS_ALL 0xFFFFFFFF
+
+/* Number of IMRs provided by Quark X1000 SoC */
+#define QUARK_X1000_IMR_MAX 0x08
+#define QUARK_X1000_IMR_REGBASE 0x40
+
+/* IMR alignment bits - only bits 31:10 are checked for IMR validity */
+#define IMR_ALIGN 0x400
+#define IMR_MASK (IMR_ALIGN - 1)
+
+int imr_add_range(phys_addr_t base, size_t size,
+ unsigned int rmask, unsigned int wmask, bool lock);
+
+int imr_remove_range(phys_addr_t base, size_t size);
+
+#endif /* _IMR_H */
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index f97fbe3abb67f5..95e11f79f123c6 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -51,6 +51,8 @@ extern int devmem_is_allowed(unsigned long pagenr);
extern unsigned long max_low_pfn_mapped;
extern unsigned long max_pfn_mapped;
+extern bool kaslr_enabled;
+
static inline phys_addr_t get_max_mapped(void)
{
return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index 7050d864f5207c..cf87de3fc39000 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -46,7 +46,7 @@ static __always_inline bool static_key_false(struct static_key *key);
static inline void __ticket_enter_slowpath(arch_spinlock_t *lock)
{
- set_bit(0, (volatile unsigned long *)&lock->tickets.tail);
+ set_bit(0, (volatile unsigned long *)&lock->tickets.head);
}
#else /* !CONFIG_PARAVIRT_SPINLOCKS */
@@ -60,10 +60,30 @@ static inline void __ticket_unlock_kick(arch_spinlock_t *lock,
}
#endif /* CONFIG_PARAVIRT_SPINLOCKS */
+static inline int __tickets_equal(__ticket_t one, __ticket_t two)
+{
+ return !((one ^ two) & ~TICKET_SLOWPATH_FLAG);
+}
+
+static inline void __ticket_check_and_clear_slowpath(arch_spinlock_t *lock,
+ __ticket_t head)
+{
+ if (head & TICKET_SLOWPATH_FLAG) {
+ arch_spinlock_t old, new;
+
+ old.tickets.head = head;
+ new.tickets.head = head & ~TICKET_SLOWPATH_FLAG;
+ old.tickets.tail = new.tickets.head + TICKET_LOCK_INC;
+ new.tickets.tail = old.tickets.tail;
+
+ /* try to clear slowpath flag when there are no contenders */
+ cmpxchg(&lock->head_tail, old.head_tail, new.head_tail);
+ }
+}
static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
{
- return lock.tickets.head == lock.tickets.tail;
+ return __tickets_equal(lock.tickets.head, lock.tickets.tail);
}
/*
@@ -87,18 +107,21 @@ static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
if (likely(inc.head == inc.tail))
goto out;
- inc.tail &= ~TICKET_SLOWPATH_FLAG;
for (;;) {
unsigned count = SPIN_THRESHOLD;
do {
- if (READ_ONCE(lock->tickets.head) == inc.tail)
- goto out;
+ inc.head = READ_ONCE(lock->tickets.head);
+ if (__tickets_equal(inc.head, inc.tail))
+ goto clear_slowpath;
cpu_relax();
} while (--count);
__ticket_lock_spinning(lock, inc.tail);
}
-out: barrier(); /* make sure nothing creeps before the lock is taken */
+clear_slowpath:
+ __ticket_check_and_clear_slowpath(lock, inc.head);
+out:
+ barrier(); /* make sure nothing creeps before the lock is taken */
}
static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
@@ -106,56 +129,30 @@ static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
arch_spinlock_t old, new;
old.tickets = READ_ONCE(lock->tickets);
- if (old.tickets.head != (old.tickets.tail & ~TICKET_SLOWPATH_FLAG))
+ if (!__tickets_equal(old.tickets.head, old.tickets.tail))
return 0;
new.head_tail = old.head_tail + (TICKET_LOCK_INC << TICKET_SHIFT);
+ new.head_tail &= ~TICKET_SLOWPATH_FLAG;
/* cmpxchg is a full barrier, so nothing can move before it */
return cmpxchg(&lock->head_tail, old.head_tail, new.head_tail) == old.head_tail;
}
-static inline void __ticket_unlock_slowpath(arch_spinlock_t *lock,
- arch_spinlock_t old)
-{
- arch_spinlock_t new;
-
- BUILD_BUG_ON(((__ticket_t)NR_CPUS) != NR_CPUS);
-
- /* Perform the unlock on the "before" copy */
- old.tickets.head += TICKET_LOCK_INC;
-
- /* Clear the slowpath flag */
- new.head_tail = old.head_tail & ~(TICKET_SLOWPATH_FLAG << TICKET_SHIFT);
-
- /*
- * If the lock is uncontended, clear the flag - use cmpxchg in
- * case it changes behind our back though.
- */
- if (new.tickets.head != new.tickets.tail ||
- cmpxchg(&lock->head_tail, old.head_tail,
- new.head_tail) != old.head_tail) {
- /*
- * Lock still has someone queued for it, so wake up an
- * appropriate waiter.
- */
- __ticket_unlock_kick(lock, old.tickets.head);
- }
-}
-
static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
{
if (TICKET_SLOWPATH_FLAG &&
- static_key_false(¶virt_ticketlocks_enabled)) {
- arch_spinlock_t prev;
+ static_key_false(¶virt_ticketlocks_enabled)) {
+ __ticket_t head;
- prev = *lock;
- add_smp(&lock->tickets.head, TICKET_LOCK_INC);
+ BUILD_BUG_ON(((__ticket_t)NR_CPUS) != NR_CPUS);
- /* add_smp() is a full mb() */
+ head = xadd(&lock->tickets.head, TICKET_LOCK_INC);
- if (unlikely(lock->tickets.tail & TICKET_SLOWPATH_FLAG))
- __ticket_unlock_slowpath(lock, prev);
+ if (unlikely(head & TICKET_SLOWPATH_FLAG)) {
+ head &= ~TICKET_SLOWPATH_FLAG;
+ __ticket_unlock_kick(lock, (head + TICKET_LOCK_INC));
+ }
} else
__add(&lock->tickets.head, TICKET_LOCK_INC, UNLOCK_LOCK_PREFIX);
}
@@ -164,14 +161,15 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
struct __raw_tickets tmp = READ_ONCE(lock->tickets);
- return tmp.tail != tmp.head;
+ return !__tickets_equal(tmp.tail, tmp.head);
}
static inline int arch_spin_is_contended(arch_spinlock_t *lock)
{
struct __raw_tickets tmp = READ_ONCE(lock->tickets);
- return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC;
+ tmp.head &= ~TICKET_SLOWPATH_FLAG;
+ return (tmp.tail - tmp.head) > TICKET_LOCK_INC;
}
#define arch_spin_is_contended arch_spin_is_contended
@@ -191,8 +189,8 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
* We need to check "unlocked" in a loop, tmp.head == head
* can be false positive because of overflow.
*/
- if (tmp.head == (tmp.tail & ~TICKET_SLOWPATH_FLAG) ||
- tmp.head != head)
+ if (__tickets_equal(tmp.head, tmp.tail) ||
+ !__tickets_equal(tmp.head, head))
break;
cpu_relax();
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 225b0988043a0a..44e6dd7e36a23b 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -7,6 +7,7 @@
#define SETUP_DTB 2
#define SETUP_PCI 3
#define SETUP_EFI 4
+#define SETUP_KASLR 5
/* ram_size flags */
#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index ae97ed0873c6e3..3d525c6124f6c7 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -613,6 +613,11 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
int rc, irq, trigger, polarity;
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+ *irqp = gsi;
+ return 0;
+ }
+
rc = acpi_get_override_irq(gsi, &trigger, &polarity);
if (rc == 0) {
trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index c6826d1e808258..746e7fd08aad70 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -196,6 +196,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
struct microcode_header_intel mc_header;
unsigned int mc_size;
+ if (leftover < sizeof(mc_header)) {
+ pr_err("error! Truncated header in microcode data file\n");
+ break;
+ }
+
if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
break;
diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c
index ec9df6f9cd47b3..420eb933189ca4 100644
--- a/arch/x86/kernel/cpu/microcode/intel_early.c
+++ b/arch/x86/kernel/cpu/microcode/intel_early.c
@@ -321,7 +321,11 @@ get_matching_model_microcode(int cpu, unsigned long start,
unsigned int mc_saved_count = mc_saved_data->mc_saved_count;
int i;
- while (leftover) {
+ while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) {
+
+ if (leftover < sizeof(mc_header))
+ break;
+
mc_header = (struct microcode_header_intel *)ucode_ptr;
mc_size = get_totalsize(mc_header);
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 705ef8d48e2dc4..67b1cbe0093adb 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -302,6 +302,9 @@ int check_irq_vectors_for_cpu_disable(void)
irq = __this_cpu_read(vector_irq[vector]);
if (irq >= 0) {
desc = irq_to_desc(irq);
+ if (!desc)
+ continue;
+
data = irq_desc_get_irq_data(desc);
cpumask_copy(&affinity_new, data->affinity);
cpu_clear(this_cpu, affinity_new);
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 98f654d466e585..6a1146ea4d4d88 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -84,7 +84,7 @@ static volatile u32 twobyte_is_boostable[256 / 32] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ---------------------------------------------- */
W(0x00, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0) | /* 00 */
- W(0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 10 */
+ W(0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1) , /* 10 */
W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 20 */
W(0x30, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */
W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 94f6434843008c..e354cc6446aba4 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -609,7 +609,7 @@ static inline void check_zero(void)
u8 ret;
u8 old;
- old = ACCESS_ONCE(zero_stats);
+ old = READ_ONCE(zero_stats);
if (unlikely(old)) {
ret = cmpxchg(&zero_stats, old, 0);
/* This ensures only one fellow resets the stat */
@@ -727,6 +727,7 @@ __visible void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
int cpu;
u64 start;
unsigned long flags;
+ __ticket_t head;
if (in_nmi())
return;
@@ -768,11 +769,15 @@ __visible void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
*/
__ticket_enter_slowpath(lock);
+ /* make sure enter_slowpath, which is atomic does not cross the read */
+ smp_mb__after_atomic();
+
/*
* check again make sure it didn't become free while
* we weren't looking.
*/
- if (ACCESS_ONCE(lock->tickets.head) == want) {
+ head = READ_ONCE(lock->tickets.head);
+ if (__tickets_equal(head, want)) {
add_stats(TAKEN_SLOW_PICKUP, 1);
goto out;
}
@@ -803,8 +808,8 @@ static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
add_stats(RELEASED_SLOW, 1);
for_each_cpu(cpu, &waiting_cpus) {
const struct kvm_lock_waiting *w = &per_cpu(klock_waiting, cpu);
- if (ACCESS_ONCE(w->lock) == lock &&
- ACCESS_ONCE(w->want) == ticket) {
+ if (READ_ONCE(w->lock) == lock &&
+ READ_ONCE(w->want) == ticket) {
add_stats(RELEASED_SLOW_KICKED, 1);
kvm_kick_cpu(cpu);
break;
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index d1ac80b72c7218..9bbb9b35c144a4 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -47,21 +47,13 @@ do { \
#ifdef CONFIG_RANDOMIZE_BASE
static unsigned long module_load_offset;
-static int randomize_modules = 1;
/* Mutex protects the module_load_offset. */
static DEFINE_MUTEX(module_kaslr_mutex);
-static int __init parse_nokaslr(char *p)
-{
- randomize_modules = 0;
- return 0;
-}
-early_param("nokaslr", parse_nokaslr);
-
static unsigned long int get_module_load_offset(void)
{
- if (randomize_modules) {
+ if (kaslr_enabled) {
mutex_lock(&module_kaslr_mutex);
/*
* Calculate the module_load_offset the first time this
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 0a2421cca01fad..98dc9317286e1e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -122,6 +122,8 @@
unsigned long max_low_pfn_mapped;
unsigned long max_pfn_mapped;
+bool __read_mostly kaslr_enabled = false;
+
#ifdef CONFIG_DMI
RESERVE_BRK(dmi_alloc, 65536);
#endif
@@ -425,6 +427,11 @@ static void __init reserve_initrd(void)
}
#endif /* CONFIG_BLK_DEV_INITRD */
+static void __init parse_kaslr_setup(u64 pa_data, u32 data_len)
+{
+ kaslr_enabled = (bool)(pa_data + sizeof(struct setup_data));
+}
+
static void __init parse_setup_data(void)
{
struct setup_data *data;
@@ -450,6 +457,9 @@ static void __init parse_setup_data(void)
case SETUP_EFI:
parse_efi_setup(pa_data, data_len);
break;
+ case SETUP_KASLR:
+ parse_kaslr_setup(pa_data, data_len);
+ break;
default:
break;
}
@@ -832,10 +842,14 @@ static void __init trim_low_memory_range(void)
static int
dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
{
- pr_emerg("Kernel Offset: 0x%lx from 0x%lx "
- "(relocation range: 0x%lx-0x%lx)\n",
- (unsigned long)&_text - __START_KERNEL, __START_KERNEL,
- __START_KERNEL_map, MODULES_VADDR-1);
+ if (kaslr_enabled)
+ pr_emerg("Kernel Offset: 0x%lx from 0x%lx (relocation range: 0x%lx-0x%lx)\n",
+ (unsigned long)&_text - __START_KERNEL,
+ __START_KERNEL,
+ __START_KERNEL_map,
+ MODULES_VADDR-1);
+ else
+ pr_emerg("Kernel Offset: disabled\n");
return 0;
}
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 8b96a947021ffe..81f8adb0679e54 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -66,27 +66,54 @@
* Good-instruction tables for 32-bit apps. This is non-const and volatile
* to keep gcc from statically optimizing it out, as variable_test_bit makes
* some versions of gcc to think only *(unsigned long*) is used.
+ *
+ * Opcodes we'll probably never support:
+ * 6c-6f - ins,outs. SEGVs if used in userspace
+ * e4-e7 - in,out imm. SEGVs if used in userspace
+ * ec-ef - in,out acc. SEGVs if used in userspace
+ * cc - int3. SIGTRAP if used in userspace
+ * ce - into. Not used in userspace - no kernel support to make it useful. SEGVs
+ * (why we support bound (62) then? it's similar, and similarly unused...)
+ * f1 - int1. SIGTRAP if used in userspace
+ * f4 - hlt. SEGVs if used in userspace
+ * fa - cli. SEGVs if used in userspace
+ * fb - sti. SEGVs if used in userspace
+ *
+ * Opcodes which need some work to be supported:
+ * 07,17,1f - pop es/ss/ds
+ * Normally not used in userspace, but would execute if used.
+ * Can cause GP or stack exception if tries to load wrong segment descriptor.
+ * We hesitate to run them under single step since kernel's handling
+ * of userspace single-stepping (TF flag) is fragile.
+ * We can easily refuse to support push es/cs/ss/ds (06/0e/16/1e)
+ * on the same grounds that they are never used.
+ * cd - int N.
+ * Used by userspace for "int 80" syscall entry. (Other "int N"
+ * cause GP -> SEGV since their IDT gates don't allow calls from CPL 3).
+ * Not supported since kernel's handling of userspace single-stepping
+ * (TF flag) is fragile.
+ * cf - iret. Normally not used in userspace. Doesn't SEGV unless arguments are bad
*/
#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
static volatile u32 good_insns_32[256 / 32] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ---------------------------------------------- */
- W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */
+ W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 00 */
W(0x10, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) , /* 10 */
- W(0x20, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) | /* 20 */
- W(0x30, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) , /* 30 */
+ W(0x20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */
+ W(0x30, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 30 */
W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */
- W(0x60, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */
+ W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */
W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */
W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */
W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */
- W(0xd0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
+ W(0xd0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */
- W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */
+ W(0xf0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */
/* ---------------------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
@@ -94,27 +121,61 @@ static volatile u32 good_insns_32[256 / 32] = {
#define good_insns_32 NULL
#endif
-/* Good-instruction tables for 64-bit apps */
+/* Good-instruction tables for 64-bit apps.
+ *
+ * Genuinely invalid opcodes:
+ * 06,07 - formerly push/pop es
+ * 0e - formerly push cs
+ * 16,17 - formerly push/pop ss
+ * 1e,1f - formerly push/pop ds
+ * 27,2f,37,3f - formerly daa/das/aaa/aas
+ * 60,61 - formerly pusha/popa
+ * 62 - formerly bound. EVEX prefix for AVX512 (not yet supported)
+ * 82 - formerly redundant encoding of Group1
+ * 9a - formerly call seg:ofs
+ * ce - formerly into
+ * d4,d5 - formerly aam/aad
+ * d6 - formerly undocumented salc
+ * ea - formerly jmp seg:ofs
+ *
+ * Opcodes we'll probably never support:
+ * 6c-6f - ins,outs. SEGVs if used in userspace
+ * e4-e7 - in,out imm. SEGVs if used in userspace
+ * ec-ef - in,out acc. SEGVs if used in userspace
+ * cc - int3. SIGTRAP if used in userspace
+ * f1 - int1. SIGTRAP if used in userspace
+ * f4 - hlt. SEGVs if used in userspace
+ * fa - cli. SEGVs if used in userspace
+ * fb - sti. SEGVs if used in userspace
+ *
+ * Opcodes which need some work to be supported:
+ * cd - int N.
+ * Used by userspace for "int 80" syscall entry. (Other "int N"
+ * cause GP -> SEGV since their IDT gates don't allow calls from CPL 3).
+ * Not supported since kernel's handling of userspace single-stepping
+ * (TF flag) is fragile.
+ * cf - iret. Normally not used in userspace. Doesn't SEGV unless arguments are bad
+ */
#if defined(CONFIG_X86_64)
static volatile u32 good_insns_64[256 / 32] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ---------------------------------------------- */
- W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */
+ W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) | /* 00 */
W(0x10, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 10 */
- W(0x20, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 20 */
- W(0x30, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 30 */
- W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */
+ W(0x20, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 20 */
+ W(0x30, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) , /* 30 */
+ W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */
- W(0x60, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */
+ W(0x60, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */
W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */
W(0x80, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
- W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
+ W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1) , /* 90 */
W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */
W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
- W(0xc0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */
+ W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */
W(0xd0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
- W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */
- W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */
+ W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0) | /* e0 */
+ W(0xf0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1) /* f0 */
/* ---------------------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
@@ -122,49 +183,55 @@ static volatile u32 good_insns_64[256 / 32] = {
#define good_insns_64 NULL
#endif
-/* Using this for both 64-bit and 32-bit apps */
+/* Using this for both 64-bit and 32-bit apps.
+ * Opcodes we don't support:
+ * 0f 00 - SLDT/STR/LLDT/LTR/VERR/VERW/-/- group. System insns
+ * 0f 01 - SGDT/SIDT/LGDT/LIDT/SMSW/-/LMSW/INVLPG group.
+ * Also encodes tons of other system insns if mod=11.
+ * Some are in fact non-system: xend, xtest, rdtscp, maybe more
+ * 0f 05 - syscall
+ * 0f 06 - clts (CPL0 insn)
+ * 0f 07 - sysret
+ * 0f 08 - invd (CPL0 insn)
+ * 0f 09 - wbinvd (CPL0 insn)
+ * 0f 0b - ud2
+ * 0f 30 - wrmsr (CPL0 insn) (then why rdmsr is allowed, it's also CPL0 insn?)
+ * 0f 34 - sysenter
+ * 0f 35 - sysexit
+ * 0f 37 - getsec
+ * 0f 78 - vmread (Intel VMX. CPL0 insn)
+ * 0f 79 - vmwrite (Intel VMX. CPL0 insn)
+ * Note: with prefixes, these two opcodes are
+ * extrq/insertq/AVX512 convert vector ops.
+ * 0f ae - group15: [f]xsave,[f]xrstor,[v]{ld,st}mxcsr,clflush[opt],
+ * {rd,wr}{fs,gs}base,{s,l,m}fence.
+ * Why? They are all user-executable.
+ */
static volatile u32 good_2byte_insns[256 / 32] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* ---------------------------------------------- */
- W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */
- W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* 10 */
- W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */
- W(0x30, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */
+ W(0x00, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1) | /* 00 */
+ W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 10 */
+ W(0x20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */
+ W(0x30, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1) , /* 30 */
W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */
W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 60 */
- W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */
+ W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1) , /* 70 */
W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
- W(0xa0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) | /* a0 */
- W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
+ W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1) | /* a0 */
+ W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */
- W(0xd0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
+ W(0xd0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* e0 */
- W(0xf0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) /* f0 */
+ W(0xf0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) /* f0 */
/* ---------------------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
#undef W
/*
- * opcodes we'll probably never support:
- *
- * 6c-6d, e4-e5, ec-ed - in
- * 6e-6f, e6-e7, ee-ef - out
- * cc, cd - int3, int
- * cf - iret
- * d6 - illegal instruction
- * f1 - int1/icebp
- * f4 - hlt
- * fa, fb - cli, sti
- * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2
- *
- * invalid opcodes in 64-bit mode:
- *
- * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5
- * 63 - we support this opcode in x86_64 but not in i386.
- *
* opcodes we may need to refine support for:
*
* 0f - 2-byte instructions: For many of these instructions, the validity
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 553c094b9cd798..a110efca6d068f 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -238,6 +238,31 @@ static void __init_refok adjust_range_page_size_mask(struct map_range *mr,
}
}
+static const char *page_size_string(struct map_range *mr)
+{
+ static const char str_1g[] = "1G";
+ static const char str_2m[] = "2M";
+ static const char str_4m[] = "4M";
+ static const char str_4k[] = "4k";
+
+ if (mr->page_size_mask & (1<page_size_mask & (1<page_size_mask & (1<flags & PF_RANDOMIZE) &&
!(current->personality & ADDR_NO_RANDOMIZE)) {
- max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT;
+ max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT;
}
return max;
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 85afde1fa3e5f6..a62e0be3a2f1b4 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -5,6 +5,7 @@ obj-y += geode/
obj-y += goldfish/
obj-y += iris/
obj-y += intel-mid/
+obj-y += intel-quark/
obj-y += olpc/
obj-y += scx200/
obj-y += sfi/
diff --git a/arch/x86/platform/efi/efi_stub_64.S b/arch/x86/platform/efi/efi_stub_64.S
index 5fcda7272550a7..86d0f9e08dd95e 100644
--- a/arch/x86/platform/efi/efi_stub_64.S
+++ b/arch/x86/platform/efi/efi_stub_64.S
@@ -91,167 +91,6 @@ ENTRY(efi_call)
ret
ENDPROC(efi_call)
-#ifdef CONFIG_EFI_MIXED
-
-/*
- * We run this function from the 1:1 mapping.
- *
- * This function must be invoked with a 1:1 mapped stack.
- */
-ENTRY(__efi64_thunk)
- movl %ds, %eax
- push %rax
- movl %es, %eax
- push %rax
- movl %ss, %eax
- push %rax
-
- subq $32, %rsp
- movl %esi, 0x0(%rsp)
- movl %edx, 0x4(%rsp)
- movl %ecx, 0x8(%rsp)
- movq %r8, %rsi
- movl %esi, 0xc(%rsp)
- movq %r9, %rsi
- movl %esi, 0x10(%rsp)
-
- sgdt save_gdt(%rip)
-
- leaq 1f(%rip), %rbx
- movq %rbx, func_rt_ptr(%rip)
-
- /* Switch to gdt with 32-bit segments */
- movl 64(%rsp), %eax
- lgdt (%rax)
-
- leaq efi_enter32(%rip), %rax
- pushq $__KERNEL_CS
- pushq %rax
- lretq
-
-1: addq $32, %rsp
-
- lgdt save_gdt(%rip)
-
- pop %rbx
- movl %ebx, %ss
- pop %rbx
- movl %ebx, %es
- pop %rbx
- movl %ebx, %ds
-
- /*
- * Convert 32-bit status code into 64-bit.
- */
- test %rax, %rax
- jz 1f
- movl %eax, %ecx
- andl $0x0fffffff, %ecx
- andl $0xf0000000, %eax
- shl $32, %rax
- or %rcx, %rax
-1:
- ret
-ENDPROC(__efi64_thunk)
-
-ENTRY(efi_exit32)
- movq func_rt_ptr(%rip), %rax
- push %rax
- mov %rdi, %rax
- ret
-ENDPROC(efi_exit32)
-
- .code32
-/*
- * EFI service pointer must be in %edi.
- *
- * The stack should represent the 32-bit calling convention.
- */
-ENTRY(efi_enter32)
- movl $__KERNEL_DS, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
-
- /* Reload pgtables */
- movl %cr3, %eax
- movl %eax, %cr3
-
- /* Disable paging */
- movl %cr0, %eax
- btrl $X86_CR0_PG_BIT, %eax
- movl %eax, %cr0
-
- /* Disable long mode via EFER */
- movl $MSR_EFER, %ecx
- rdmsr
- btrl $_EFER_LME, %eax
- wrmsr
-
- call *%edi
-
- /* We must preserve return value */
- movl %eax, %edi
-
- /*
- * Some firmware will return with interrupts enabled. Be sure to
- * disable them before we switch GDTs.
- */
- cli
-
- movl 68(%esp), %eax
- movl %eax, 2(%eax)
- lgdtl (%eax)
-
- movl %cr4, %eax
- btsl $(X86_CR4_PAE_BIT), %eax
- movl %eax, %cr4
-
- movl %cr3, %eax
- movl %eax, %cr3
-
- movl $MSR_EFER, %ecx
- rdmsr
- btsl $_EFER_LME, %eax
- wrmsr
-
- xorl %eax, %eax
- lldt %ax
-
- movl 72(%esp), %eax
- pushl $__KERNEL_CS
- pushl %eax
-
- /* Enable paging */
- movl %cr0, %eax
- btsl $X86_CR0_PG_BIT, %eax
- movl %eax, %cr0
- lret
-ENDPROC(efi_enter32)
-
- .data
- .balign 8
- .global efi32_boot_gdt
-efi32_boot_gdt: .word 0
- .quad 0
-
-save_gdt: .word 0
- .quad 0
-func_rt_ptr: .quad 0
-
- .global efi_gdt64
-efi_gdt64:
- .word efi_gdt64_end - efi_gdt64
- .long 0 /* Filled out by user */
- .word 0
- .quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x00af9a000000ffff /* __KERNEL_CS */
- .quad 0x00cf92000000ffff /* __KERNEL_DS */
- .quad 0x0080890000000000 /* TS descriptor */
- .quad 0x0000000000000000 /* TS continued */
-efi_gdt64_end:
-#endif /* CONFIG_EFI_MIXED */
-
.data
ENTRY(efi_scratch)
.fill 3,8,0
diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
index 8806fa73e6e6d2..ff85d28c50f261 100644
--- a/arch/x86/platform/efi/efi_thunk_64.S
+++ b/arch/x86/platform/efi/efi_thunk_64.S
@@ -1,9 +1,26 @@
/*
* Copyright (C) 2014 Intel Corporation; author Matt Fleming
+ *
+ * Support for invoking 32-bit EFI runtime services from a 64-bit
+ * kernel.
+ *
+ * The below thunking functions are only used after ExitBootServices()
+ * has been called. This simplifies things considerably as compared with
+ * the early EFI thunking because we can leave all the kernel state
+ * intact (GDT, IDT, etc) and simply invoke the the 32-bit EFI runtime
+ * services from __KERNEL32_CS. This means we can continue to service
+ * interrupts across an EFI mixed mode call.
+ *
+ * We do however, need to handle the fact that we're running in a full
+ * 64-bit virtual address space. Things like the stack and instruction
+ * addresses need to be accessible by the 32-bit firmware, so we rely on
+ * using the identity mappings in the EFI page table to access the stack
+ * and kernel text (see efi_setup_page_tables()).
*/
#include
#include
+#include
.text
.code64
@@ -33,14 +50,6 @@ ENTRY(efi64_thunk)
leaq efi_exit32(%rip), %rbx
subq %rax, %rbx
movl %ebx, 8(%rsp)
- leaq efi_gdt64(%rip), %rbx
- subq %rax, %rbx
- movl %ebx, 2(%ebx)
- movl %ebx, 4(%rsp)
- leaq efi_gdt32(%rip), %rbx
- subq %rax, %rbx
- movl %ebx, 2(%ebx)
- movl %ebx, (%rsp)
leaq __efi64_thunk(%rip), %rbx
subq %rax, %rbx
@@ -52,14 +61,92 @@ ENTRY(efi64_thunk)
retq
ENDPROC(efi64_thunk)
- .data
-efi_gdt32:
- .word efi_gdt32_end - efi_gdt32
- .long 0 /* Filled out above */
- .word 0
- .quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x00cf9a000000ffff /* __KERNEL_CS */
- .quad 0x00cf93000000ffff /* __KERNEL_DS */
-efi_gdt32_end:
+/*
+ * We run this function from the 1:1 mapping.
+ *
+ * This function must be invoked with a 1:1 mapped stack.
+ */
+ENTRY(__efi64_thunk)
+ movl %ds, %eax
+ push %rax
+ movl %es, %eax
+ push %rax
+ movl %ss, %eax
+ push %rax
+
+ subq $32, %rsp
+ movl %esi, 0x0(%rsp)
+ movl %edx, 0x4(%rsp)
+ movl %ecx, 0x8(%rsp)
+ movq %r8, %rsi
+ movl %esi, 0xc(%rsp)
+ movq %r9, %rsi
+ movl %esi, 0x10(%rsp)
+
+ leaq 1f(%rip), %rbx
+ movq %rbx, func_rt_ptr(%rip)
+
+ /* Switch to 32-bit descriptor */
+ pushq $__KERNEL32_CS
+ leaq efi_enter32(%rip), %rax
+ pushq %rax
+ lretq
+
+1: addq $32, %rsp
+
+ pop %rbx
+ movl %ebx, %ss
+ pop %rbx
+ movl %ebx, %es
+ pop %rbx
+ movl %ebx, %ds
+ /*
+ * Convert 32-bit status code into 64-bit.
+ */
+ test %rax, %rax
+ jz 1f
+ movl %eax, %ecx
+ andl $0x0fffffff, %ecx
+ andl $0xf0000000, %eax
+ shl $32, %rax
+ or %rcx, %rax
+1:
+ ret
+ENDPROC(__efi64_thunk)
+
+ENTRY(efi_exit32)
+ movq func_rt_ptr(%rip), %rax
+ push %rax
+ mov %rdi, %rax
+ ret
+ENDPROC(efi_exit32)
+
+ .code32
+/*
+ * EFI service pointer must be in %edi.
+ *
+ * The stack should represent the 32-bit calling convention.
+ */
+ENTRY(efi_enter32)
+ movl $__KERNEL_DS, %eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+
+ call *%edi
+
+ /* We must preserve return value */
+ movl %eax, %edi
+
+ movl 72(%esp), %eax
+ pushl $__KERNEL_CS
+ pushl %eax
+
+ lret
+ENDPROC(efi_enter32)
+
+ .data
+ .balign 8
+func_rt_ptr: .quad 0
efi_saved_sp: .quad 0
diff --git a/arch/x86/platform/intel-quark/Makefile b/arch/x86/platform/intel-quark/Makefile
new file mode 100644
index 00000000000000..9cc57ed360224f
--- /dev/null
+++ b/arch/x86/platform/intel-quark/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_INTEL_IMR) += imr.o
+obj-$(CONFIG_DEBUG_IMR_SELFTEST) += imr_selftest.o
diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c
new file mode 100644
index 00000000000000..0ee619f9fcb725
--- /dev/null
+++ b/arch/x86/platform/intel-quark/imr.c
@@ -0,0 +1,661 @@
+/**
+ * imr.c
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2015 Bryan O'Donoghue
+ *
+ * IMR registers define an isolated region of memory that can
+ * be masked to prohibit certain system agents from accessing memory.
+ * When a device behind a masked port performs an access - snooped or
+ * not, an IMR may optionally prevent that transaction from changing
+ * the state of memory or from getting correct data in response to the
+ * operation.
+ *
+ * Write data will be dropped and reads will return 0xFFFFFFFF, the
+ * system will reset and system BIOS will print out an error message to
+ * inform the user that an IMR has been violated.
+ *
+ * This code is based on the Linux MTRR code and reference code from
+ * Intel's Quark BSP EFI, Linux and grub code.
+ *
+ * See quark-x1000-datasheet.pdf for register definitions.
+ * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/quark-x1000-datasheet.pdf
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct imr_device {
+ struct dentry *file;
+ bool init;
+ struct mutex lock;
+ int max_imr;
+ int reg_base;
+};
+
+static struct imr_device imr_dev;
+
+/*
+ * IMR read/write mask control registers.
+ * See quark-x1000-datasheet.pdf sections 12.7.4.5 and 12.7.4.6 for
+ * bit definitions.
+ *
+ * addr_hi
+ * 31 Lock bit
+ * 30:24 Reserved
+ * 23:2 1 KiB aligned lo address
+ * 1:0 Reserved
+ *
+ * addr_hi
+ * 31:24 Reserved
+ * 23:2 1 KiB aligned hi address
+ * 1:0 Reserved
+ */
+#define IMR_LOCK BIT(31)
+
+struct imr_regs {
+ u32 addr_lo;
+ u32 addr_hi;
+ u32 rmask;
+ u32 wmask;
+};
+
+#define IMR_NUM_REGS (sizeof(struct imr_regs)/sizeof(u32))
+#define IMR_SHIFT 8
+#define imr_to_phys(x) ((x) << IMR_SHIFT)
+#define phys_to_imr(x) ((x) >> IMR_SHIFT)
+
+/**
+ * imr_is_enabled - true if an IMR is enabled false otherwise.
+ *
+ * Determines if an IMR is enabled based on address range and read/write
+ * mask. An IMR set with an address range set to zero and a read/write
+ * access mask set to all is considered to be disabled. An IMR in any
+ * other state - for example set to zero but without read/write access
+ * all is considered to be enabled. This definition of disabled is how
+ * firmware switches off an IMR and is maintained in kernel for
+ * consistency.
+ *
+ * @imr: pointer to IMR descriptor.
+ * @return: true if IMR enabled false if disabled.
+ */
+static inline int imr_is_enabled(struct imr_regs *imr)
+{
+ return !(imr->rmask == IMR_READ_ACCESS_ALL &&
+ imr->wmask == IMR_WRITE_ACCESS_ALL &&
+ imr_to_phys(imr->addr_lo) == 0 &&
+ imr_to_phys(imr->addr_hi) == 0);
+}
+
+/**
+ * imr_read - read an IMR at a given index.
+ *
+ * Requires caller to hold imr mutex.
+ *
+ * @idev: pointer to imr_device structure.
+ * @imr_id: IMR entry to read.
+ * @imr: IMR structure representing address and access masks.
+ * @return: 0 on success or error code passed from mbi_iosf on failure.
+ */
+static int imr_read(struct imr_device *idev, u32 imr_id, struct imr_regs *imr)
+{
+ u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
+ int ret;
+
+ ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
+ reg++, &imr->addr_lo);
+ if (ret)
+ return ret;
+
+ ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
+ reg++, &imr->addr_hi);
+ if (ret)
+ return ret;
+
+ ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
+ reg++, &imr->rmask);
+ if (ret)
+ return ret;
+
+ return iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
+ reg++, &imr->wmask);
+}
+
+/**
+ * imr_write - write an IMR at a given index.
+ *
+ * Requires caller to hold imr mutex.
+ * Note lock bits need to be written independently of address bits.
+ *
+ * @idev: pointer to imr_device structure.
+ * @imr_id: IMR entry to write.
+ * @imr: IMR structure representing address and access masks.
+ * @lock: indicates if the IMR lock bit should be applied.
+ * @return: 0 on success or error code passed from mbi_iosf on failure.
+ */
+static int imr_write(struct imr_device *idev, u32 imr_id,
+ struct imr_regs *imr, bool lock)
+{
+ unsigned long flags;
+ u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
+ int ret;
+
+ local_irq_save(flags);
+
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE, reg++,
+ imr->addr_lo);
+ if (ret)
+ goto failed;
+
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
+ reg++, imr->addr_hi);
+ if (ret)
+ goto failed;
+
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
+ reg++, imr->rmask);
+ if (ret)
+ goto failed;
+
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
+ reg++, imr->wmask);
+ if (ret)
+ goto failed;
+
+ /* Lock bit must be set separately to addr_lo address bits. */
+ if (lock) {
+ imr->addr_lo |= IMR_LOCK;
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
+ reg - IMR_NUM_REGS, imr->addr_lo);
+ if (ret)
+ goto failed;
+ }
+
+ local_irq_restore(flags);
+ return 0;
+failed:
+ /*
+ * If writing to the IOSF failed then we're in an unknown state,
+ * likely a very bad state. An IMR in an invalid state will almost
+ * certainly lead to a memory access violation.
+ */
+ local_irq_restore(flags);
+ WARN(ret, "IOSF-MBI write fail range 0x%08x-0x%08x unreliable\n",
+ imr_to_phys(imr->addr_lo), imr_to_phys(imr->addr_hi) + IMR_MASK);
+
+ return ret;
+}
+
+/**
+ * imr_dbgfs_state_show - print state of IMR registers.
+ *
+ * @s: pointer to seq_file for output.
+ * @unused: unused parameter.
+ * @return: 0 on success or error code passed from mbi_iosf on failure.
+ */
+static int imr_dbgfs_state_show(struct seq_file *s, void *unused)
+{
+ phys_addr_t base;
+ phys_addr_t end;
+ int i;
+ struct imr_device *idev = s->private;
+ struct imr_regs imr;
+ size_t size;
+ int ret = -ENODEV;
+
+ mutex_lock(&idev->lock);
+
+ for (i = 0; i < idev->max_imr; i++) {
+
+ ret = imr_read(idev, i, &imr);
+ if (ret)
+ break;
+
+ /*
+ * Remember to add IMR_ALIGN bytes to size to indicate the
+ * inherent IMR_ALIGN size bytes contained in the masked away
+ * lower ten bits.
+ */
+ if (imr_is_enabled(&imr)) {
+ base = imr_to_phys(imr.addr_lo);
+ end = imr_to_phys(imr.addr_hi) + IMR_MASK;
+ } else {
+ base = 0;
+ end = 0;
+ }
+ size = end - base;
+ seq_printf(s, "imr%02i: base=%pa, end=%pa, size=0x%08zx "
+ "rmask=0x%08x, wmask=0x%08x, %s, %s\n", i,
+ &base, &end, size, imr.rmask, imr.wmask,
+ imr_is_enabled(&imr) ? "enabled " : "disabled",
+ imr.addr_lo & IMR_LOCK ? "locked" : "unlocked");
+ }
+
+ mutex_unlock(&idev->lock);
+ return ret;
+}
+
+/**
+ * imr_state_open - debugfs open callback.
+ *
+ * @inode: pointer to struct inode.
+ * @file: pointer to struct file.
+ * @return: result of single open.
+ */
+static int imr_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, imr_dbgfs_state_show, inode->i_private);
+}
+
+static const struct file_operations imr_state_ops = {
+ .open = imr_state_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/**
+ * imr_debugfs_register - register debugfs hooks.
+ *
+ * @idev: pointer to imr_device structure.
+ * @return: 0 on success - errno on failure.
+ */
+static int imr_debugfs_register(struct imr_device *idev)
+{
+ idev->file = debugfs_create_file("imr_state", S_IFREG | S_IRUGO, NULL,
+ idev, &imr_state_ops);
+ return PTR_ERR_OR_ZERO(idev->file);
+}
+
+/**
+ * imr_debugfs_unregister - unregister debugfs hooks.
+ *
+ * @idev: pointer to imr_device structure.
+ * @return:
+ */
+static void imr_debugfs_unregister(struct imr_device *idev)
+{
+ debugfs_remove(idev->file);
+}
+
+/**
+ * imr_check_params - check passed address range IMR alignment and non-zero size
+ *
+ * @base: base address of intended IMR.
+ * @size: size of intended IMR.
+ * @return: zero on valid range -EINVAL on unaligned base/size.
+ */
+static int imr_check_params(phys_addr_t base, size_t size)
+{
+ if ((base & IMR_MASK) || (size & IMR_MASK)) {
+ pr_err("base %pa size 0x%08zx must align to 1KiB\n",
+ &base, size);
+ return -EINVAL;
+ }
+ if (size == 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * imr_raw_size - account for the IMR_ALIGN bytes that addr_hi appends.
+ *
+ * IMR addr_hi has a built in offset of plus IMR_ALIGN (0x400) bytes from the
+ * value in the register. We need to subtract IMR_ALIGN bytes from input sizes
+ * as a result.
+ *
+ * @size: input size bytes.
+ * @return: reduced size.
+ */
+static inline size_t imr_raw_size(size_t size)
+{
+ return size - IMR_ALIGN;
+}
+
+/**
+ * imr_address_overlap - detects an address overlap.
+ *
+ * @addr: address to check against an existing IMR.
+ * @imr: imr being checked.
+ * @return: true for overlap false for no overlap.
+ */
+static inline int imr_address_overlap(phys_addr_t addr, struct imr_regs *imr)
+{
+ return addr >= imr_to_phys(imr->addr_lo) && addr <= imr_to_phys(imr->addr_hi);
+}
+
+/**
+ * imr_add_range - add an Isolated Memory Region.
+ *
+ * @base: physical base address of region aligned to 1KiB.
+ * @size: physical size of region in bytes must be aligned to 1KiB.
+ * @read_mask: read access mask.
+ * @write_mask: write access mask.
+ * @lock: indicates whether or not to permanently lock this region.
+ * @return: zero on success or negative value indicating error.
+ */
+int imr_add_range(phys_addr_t base, size_t size,
+ unsigned int rmask, unsigned int wmask, bool lock)
+{
+ phys_addr_t end;
+ unsigned int i;
+ struct imr_device *idev = &imr_dev;
+ struct imr_regs imr;
+ size_t raw_size;
+ int reg;
+ int ret;
+
+ if (WARN_ONCE(idev->init == false, "driver not initialized"))
+ return -ENODEV;
+
+ ret = imr_check_params(base, size);
+ if (ret)
+ return ret;
+
+ /* Tweak the size value. */
+ raw_size = imr_raw_size(size);
+ end = base + raw_size;
+
+ /*
+ * Check for reserved IMR value common to firmware, kernel and grub
+ * indicating a disabled IMR.
+ */
+ imr.addr_lo = phys_to_imr(base);
+ imr.addr_hi = phys_to_imr(end);
+ imr.rmask = rmask;
+ imr.wmask = wmask;
+ if (!imr_is_enabled(&imr))
+ return -ENOTSUPP;
+
+ mutex_lock(&idev->lock);
+
+ /*
+ * Find a free IMR while checking for an existing overlapping range.
+ * Note there's no restriction in silicon to prevent IMR overlaps.
+ * For the sake of simplicity and ease in defining/debugging an IMR
+ * memory map we exclude IMR overlaps.
+ */
+ reg = -1;
+ for (i = 0; i < idev->max_imr; i++) {
+ ret = imr_read(idev, i, &imr);
+ if (ret)
+ goto failed;
+
+ /* Find overlap @ base or end of requested range. */
+ ret = -EINVAL;
+ if (imr_is_enabled(&imr)) {
+ if (imr_address_overlap(base, &imr))
+ goto failed;
+ if (imr_address_overlap(end, &imr))
+ goto failed;
+ } else {
+ reg = i;
+ }
+ }
+
+ /* Error out if we have no free IMR entries. */
+ if (reg == -1) {
+ ret = -ENOMEM;
+ goto failed;
+ }
+
+ pr_debug("add %d phys %pa-%pa size %zx mask 0x%08x wmask 0x%08x\n",
+ reg, &base, &end, raw_size, rmask, wmask);
+
+ /* Enable IMR at specified range and access mask. */
+ imr.addr_lo = phys_to_imr(base);
+ imr.addr_hi = phys_to_imr(end);
+ imr.rmask = rmask;
+ imr.wmask = wmask;
+
+ ret = imr_write(idev, reg, &imr, lock);
+ if (ret < 0) {
+ /*
+ * In the highly unlikely event iosf_mbi_write failed
+ * attempt to rollback the IMR setup skipping the trapping
+ * of further IOSF write failures.
+ */
+ imr.addr_lo = 0;
+ imr.addr_hi = 0;
+ imr.rmask = IMR_READ_ACCESS_ALL;
+ imr.wmask = IMR_WRITE_ACCESS_ALL;
+ imr_write(idev, reg, &imr, false);
+ }
+failed:
+ mutex_unlock(&idev->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(imr_add_range);
+
+/**
+ * __imr_remove_range - delete an Isolated Memory Region.
+ *
+ * This function allows you to delete an IMR by its index specified by reg or
+ * by address range specified by base and size respectively. If you specify an
+ * index on its own the base and size parameters are ignored.
+ * imr_remove_range(0, base, size); delete IMR at index 0 base/size ignored.
+ * imr_remove_range(-1, base, size); delete IMR from base to base+size.
+ *
+ * @reg: imr index to remove.
+ * @base: physical base address of region aligned to 1 KiB.
+ * @size: physical size of region in bytes aligned to 1 KiB.
+ * @return: -EINVAL on invalid range or out or range id
+ * -ENODEV if reg is valid but no IMR exists or is locked
+ * 0 on success.
+ */
+static int __imr_remove_range(int reg, phys_addr_t base, size_t size)
+{
+ phys_addr_t end;
+ bool found = false;
+ unsigned int i;
+ struct imr_device *idev = &imr_dev;
+ struct imr_regs imr;
+ size_t raw_size;
+ int ret = 0;
+
+ if (WARN_ONCE(idev->init == false, "driver not initialized"))
+ return -ENODEV;
+
+ /*
+ * Validate address range if deleting by address, else we are
+ * deleting by index where base and size will be ignored.
+ */
+ if (reg == -1) {
+ ret = imr_check_params(base, size);
+ if (ret)
+ return ret;
+ }
+
+ /* Tweak the size value. */
+ raw_size = imr_raw_size(size);
+ end = base + raw_size;
+
+ mutex_lock(&idev->lock);
+
+ if (reg >= 0) {
+ /* If a specific IMR is given try to use it. */
+ ret = imr_read(idev, reg, &imr);
+ if (ret)
+ goto failed;
+
+ if (!imr_is_enabled(&imr) || imr.addr_lo & IMR_LOCK) {
+ ret = -ENODEV;
+ goto failed;
+ }
+ found = true;
+ } else {
+ /* Search for match based on address range. */
+ for (i = 0; i < idev->max_imr; i++) {
+ ret = imr_read(idev, i, &imr);
+ if (ret)
+ goto failed;
+
+ if (!imr_is_enabled(&imr) || imr.addr_lo & IMR_LOCK)
+ continue;
+
+ if ((imr_to_phys(imr.addr_lo) == base) &&
+ (imr_to_phys(imr.addr_hi) == end)) {
+ found = true;
+ reg = i;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ ret = -ENODEV;
+ goto failed;
+ }
+
+ pr_debug("remove %d phys %pa-%pa size %zx\n", reg, &base, &end, raw_size);
+
+ /* Tear down the IMR. */
+ imr.addr_lo = 0;
+ imr.addr_hi = 0;
+ imr.rmask = IMR_READ_ACCESS_ALL;
+ imr.wmask = IMR_WRITE_ACCESS_ALL;
+
+ ret = imr_write(idev, reg, &imr, false);
+
+failed:
+ mutex_unlock(&idev->lock);
+ return ret;
+}
+
+/**
+ * imr_remove_range - delete an Isolated Memory Region by address
+ *
+ * This function allows you to delete an IMR by an address range specified
+ * by base and size respectively.
+ * imr_remove_range(base, size); delete IMR from base to base+size.
+ *
+ * @base: physical base address of region aligned to 1 KiB.
+ * @size: physical size of region in bytes aligned to 1 KiB.
+ * @return: -EINVAL on invalid range or out or range id
+ * -ENODEV if reg is valid but no IMR exists or is locked
+ * 0 on success.
+ */
+int imr_remove_range(phys_addr_t base, size_t size)
+{
+ return __imr_remove_range(-1, base, size);
+}
+EXPORT_SYMBOL_GPL(imr_remove_range);
+
+/**
+ * imr_clear - delete an Isolated Memory Region by index
+ *
+ * This function allows you to delete an IMR by an address range specified
+ * by the index of the IMR. Useful for initial sanitization of the IMR
+ * address map.
+ * imr_ge(base, size); delete IMR from base to base+size.
+ *
+ * @reg: imr index to remove.
+ * @return: -EINVAL on invalid range or out or range id
+ * -ENODEV if reg is valid but no IMR exists or is locked
+ * 0 on success.
+ */
+static inline int imr_clear(int reg)
+{
+ return __imr_remove_range(reg, 0, 0);
+}
+
+/**
+ * imr_fixup_memmap - Tear down IMRs used during bootup.
+ *
+ * BIOS and Grub both setup IMRs around compressed kernel, initrd memory
+ * that need to be removed before the kernel hands out one of the IMR
+ * encased addresses to a downstream DMA agent such as the SD or Ethernet.
+ * IMRs on Galileo are setup to immediately reset the system on violation.
+ * As a result if you're running a root filesystem from SD - you'll need
+ * the boot-time IMRs torn down or you'll find seemingly random resets when
+ * using your filesystem.
+ *
+ * @idev: pointer to imr_device structure.
+ * @return:
+ */
+static void __init imr_fixup_memmap(struct imr_device *idev)
+{
+ phys_addr_t base = virt_to_phys(&_text);
+ size_t size = virt_to_phys(&__end_rodata) - base;
+ int i;
+ int ret;
+
+ /* Tear down all existing unlocked IMRs. */
+ for (i = 0; i < idev->max_imr; i++)
+ imr_clear(i);
+
+ /*
+ * Setup a locked IMR around the physical extent of the kernel
+ * from the beginning of the .text secton to the end of the
+ * .rodata section as one physically contiguous block.
+ */
+ ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, true);
+ if (ret < 0) {
+ pr_err("unable to setup IMR for kernel: (%p - %p)\n",
+ &_text, &__end_rodata);
+ } else {
+ pr_info("protecting kernel .text - .rodata: %zu KiB (%p - %p)\n",
+ size / 1024, &_text, &__end_rodata);
+ }
+
+}
+
+static const struct x86_cpu_id imr_ids[] __initconst = {
+ { X86_VENDOR_INTEL, 5, 9 }, /* Intel Quark SoC X1000. */
+ {}
+};
+MODULE_DEVICE_TABLE(x86cpu, imr_ids);
+
+/**
+ * imr_init - entry point for IMR driver.
+ *
+ * return: -ENODEV for no IMR support 0 if good to go.
+ */
+static int __init imr_init(void)
+{
+ struct imr_device *idev = &imr_dev;
+ int ret;
+
+ if (!x86_match_cpu(imr_ids) || !iosf_mbi_available())
+ return -ENODEV;
+
+ idev->max_imr = QUARK_X1000_IMR_MAX;
+ idev->reg_base = QUARK_X1000_IMR_REGBASE;
+ idev->init = true;
+
+ mutex_init(&idev->lock);
+ ret = imr_debugfs_register(idev);
+ if (ret != 0)
+ pr_warn("debugfs register failed!\n");
+ imr_fixup_memmap(idev);
+ return 0;
+}
+
+/**
+ * imr_exit - exit point for IMR code.
+ *
+ * Deregisters debugfs, leave IMR state as-is.
+ *
+ * return:
+ */
+static void __exit imr_exit(void)
+{
+ imr_debugfs_unregister(&imr_dev);
+}
+
+module_init(imr_init);
+module_exit(imr_exit);
+
+MODULE_AUTHOR("Bryan O'Donoghue ");
+MODULE_DESCRIPTION("Intel Isolated Memory Region driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/arch/x86/platform/intel-quark/imr_selftest.c b/arch/x86/platform/intel-quark/imr_selftest.c
new file mode 100644
index 00000000000000..c9a0838890e241
--- /dev/null
+++ b/arch/x86/platform/intel-quark/imr_selftest.c
@@ -0,0 +1,129 @@
+/**
+ * imr_selftest.c
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ * Copyright(c) 2015 Bryan O'Donoghue
+ *
+ * IMR self test. The purpose of this module is to run a set of tests on the
+ * IMR API to validate it's sanity. We check for overlapping, reserved
+ * addresses and setup/teardown sanity.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define SELFTEST KBUILD_MODNAME ": "
+/**
+ * imr_self_test_result - Print result string for self test.
+ *
+ * @res: result code - true if test passed false otherwise.
+ * @fmt: format string.
+ * ... variadic argument list.
+ */
+static void __init imr_self_test_result(int res, const char *fmt, ...)
+{
+ va_list vlist;
+
+ /* Print pass/fail. */
+ if (res)
+ pr_info(SELFTEST "pass ");
+ else
+ pr_info(SELFTEST "fail ");
+
+ /* Print variable string. */
+ va_start(vlist, fmt);
+ vprintk(fmt, vlist);
+ va_end(vlist);
+
+ /* Optional warning. */
+ WARN(res == 0, "test failed");
+}
+#undef SELFTEST
+
+/**
+ * imr_self_test
+ *
+ * Verify IMR self_test with some simple tests to verify overlap,
+ * zero sized allocations and 1 KiB sized areas.
+ *
+ */
+static void __init imr_self_test(void)
+{
+ phys_addr_t base = virt_to_phys(&_text);
+ size_t size = virt_to_phys(&__end_rodata) - base;
+ const char *fmt_over = "overlapped IMR @ (0x%08lx - 0x%08lx)\n";
+ int ret;
+
+ /* Test zero zero. */
+ ret = imr_add_range(0, 0, 0, 0, false);
+ imr_self_test_result(ret < 0, "zero sized IMR\n");
+
+ /* Test exact overlap. */
+ ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
+ imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
+
+ /* Test overlap with base inside of existing. */
+ base += size - IMR_ALIGN;
+ ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
+ imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
+
+ /* Test overlap with end inside of existing. */
+ base -= size + IMR_ALIGN * 2;
+ ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
+ imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
+
+ /* Test that a 1 KiB IMR @ zero with read/write all will bomb out. */
+ ret = imr_add_range(0, IMR_ALIGN, IMR_READ_ACCESS_ALL,
+ IMR_WRITE_ACCESS_ALL, false);
+ imr_self_test_result(ret < 0, "1KiB IMR @ 0x00000000 - access-all\n");
+
+ /* Test that a 1 KiB IMR @ zero with CPU only will work. */
+ ret = imr_add_range(0, IMR_ALIGN, IMR_CPU, IMR_CPU, false);
+ imr_self_test_result(ret >= 0, "1KiB IMR @ 0x00000000 - cpu-access\n");
+ if (ret >= 0) {
+ ret = imr_remove_range(0, IMR_ALIGN);
+ imr_self_test_result(ret == 0, "teardown - cpu-access\n");
+ }
+
+ /* Test 2 KiB works. */
+ size = IMR_ALIGN * 2;
+ ret = imr_add_range(0, size, IMR_READ_ACCESS_ALL,
+ IMR_WRITE_ACCESS_ALL, false);
+ imr_self_test_result(ret >= 0, "2KiB IMR @ 0x00000000\n");
+ if (ret >= 0) {
+ ret = imr_remove_range(0, size);
+ imr_self_test_result(ret == 0, "teardown 2KiB\n");
+ }
+}
+
+/**
+ * imr_self_test_init - entry point for IMR driver.
+ *
+ * return: -ENODEV for no IMR support 0 if good to go.
+ */
+static int __init imr_self_test_init(void)
+{
+ imr_self_test();
+ return 0;
+}
+
+/**
+ * imr_self_test_exit - exit point for IMR code.
+ *
+ * return:
+ */
+static void __exit imr_self_test_exit(void)
+{
+}
+
+module_init(imr_self_test_init);
+module_exit(imr_self_test_exit);
+
+MODULE_AUTHOR("Bryan O'Donoghue ");
+MODULE_DESCRIPTION("Intel Isolated Memory Region self-test driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 23b45eb9a89ce4..956374c1edbc31 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -41,7 +41,7 @@ static u8 zero_stats;
static inline void check_zero(void)
{
u8 ret;
- u8 old = ACCESS_ONCE(zero_stats);
+ u8 old = READ_ONCE(zero_stats);
if (unlikely(old)) {
ret = cmpxchg(&zero_stats, old, 0);
/* This ensures only one fellow resets the stat */
@@ -112,6 +112,7 @@ __visible void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
struct xen_lock_waiting *w = this_cpu_ptr(&lock_waiting);
int cpu = smp_processor_id();
u64 start;
+ __ticket_t head;
unsigned long flags;
/* If kicker interrupts not initialized yet, just spin */
@@ -159,11 +160,15 @@ __visible void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
*/
__ticket_enter_slowpath(lock);
+ /* make sure enter_slowpath, which is atomic does not cross the read */
+ smp_mb__after_atomic();
+
/*
* check again make sure it didn't become free while
* we weren't looking
*/
- if (ACCESS_ONCE(lock->tickets.head) == want) {
+ head = READ_ONCE(lock->tickets.head);
+ if (__tickets_equal(head, want)) {
add_stats(TAKEN_SLOW_PICKUP, 1);
goto out;
}
@@ -204,8 +209,8 @@ static void xen_unlock_kick(struct arch_spinlock *lock, __ticket_t next)
const struct xen_lock_waiting *w = &per_cpu(lock_waiting, cpu);
/* Make sure we read lock before want */
- if (ACCESS_ONCE(w->lock) == lock &&
- ACCESS_ONCE(w->want) == next) {
+ if (READ_ONCE(w->lock) == lock &&
+ READ_ONCE(w->want) == next) {
add_stats(RELEASED_SLOW_KICKED, 1);
xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR);
break;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 9273d0969ebd63..5b9c6d5c3636ad 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1292,6 +1292,9 @@ static u64 tg_prfill_cpu_rwstat(struct seq_file *sf,
struct blkg_rwstat rwstat = { }, tmp;
int i, cpu;
+ if (tg->stats_cpu == NULL)
+ return 0;
+
for_each_possible_cpu(cpu) {
struct tg_stats_cpu *sc = per_cpu_ptr(tg->stats_cpu, cpu);
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 02e835f3cf8aa7..657964e8ab7ed2 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -105,7 +105,7 @@ static void lpss_uart_setup(struct lpss_private_data *pdata)
}
}
-static void byt_i2c_setup(struct lpss_private_data *pdata)
+static void lpss_deassert_reset(struct lpss_private_data *pdata)
{
unsigned int offset;
u32 val;
@@ -114,9 +114,18 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
val = readl(pdata->mmio_base + offset);
val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
writel(val, pdata->mmio_base + offset);
+}
+
+#define LPSS_I2C_ENABLE 0x6c
+
+static void byt_i2c_setup(struct lpss_private_data *pdata)
+{
+ lpss_deassert_reset(pdata);
if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset))
pdata->fixed_clk_rate = 133000000;
+
+ writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
}
static struct lpss_device_desc lpt_dev_desc = {
@@ -125,7 +134,7 @@ static struct lpss_device_desc lpt_dev_desc = {
};
static struct lpss_device_desc lpt_i2c_dev_desc = {
- .flags = LPSS_CLK | LPSS_LTR,
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
.prv_offset = 0x800,
};
@@ -166,6 +175,12 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
.setup = byt_i2c_setup,
};
+static struct lpss_device_desc bsw_spi_dev_desc = {
+ .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
+ .prv_offset = 0x400,
+ .setup = lpss_deassert_reset,
+};
+
#else
#define LPSS_ADDR(desc) (0UL)
@@ -198,7 +213,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
/* Braswell LPSS devices */
{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
- { "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
+ { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 982b67faaaf32c..a8dd2f7633822b 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -680,7 +680,7 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
/* Enable GPE for event processing (SCI_EVT=1) */
if (!resuming)
acpi_ec_submit_request(ec);
- pr_info("+++++ EC started +++++\n");
+ pr_debug("EC started\n");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
@@ -712,7 +712,7 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
acpi_ec_complete_request(ec);
clear_bit(EC_FLAGS_STARTED, &ec->flags);
clear_bit(EC_FLAGS_STOPPED, &ec->flags);
- pr_info("+++++ EC stopped +++++\n");
+ pr_debug("EC stopped\n");
}
spin_unlock_irqrestore(&ec->lock, flags);
}
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 4752b99399870e..c723668e3e277d 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -46,7 +46,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
if (len && reslen && reslen == len && start <= end)
return true;
- pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
+ pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
io ? "io" : "mem", start, end, len);
return false;
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 88a4f99dd2a7cc..debd30917010a1 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -540,6 +540,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
},
},
+ {
+ /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
+ .callback = video_disable_native_backlight,
+ .ident = "SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "900X3C/900X3D/900X3E/900X4C/900X4D"),
+ },
+ },
{
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index cbdfbbf983927e..b64bccbb78c9a5 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -37,17 +37,18 @@
#include
#include
#include
+#include
#include
#include
#include
+#define NVME_MINORS (1U << MINORBITS)
#define NVME_Q_DEPTH 1024
#define NVME_AQ_DEPTH 64
#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion))
#define ADMIN_TIMEOUT (admin_timeout * HZ)
#define SHUTDOWN_TIMEOUT (shutdown_timeout * HZ)
-#define IOD_TIMEOUT (retry_time * HZ)
static unsigned char admin_timeout = 60;
module_param(admin_timeout, byte, 0644);
@@ -57,10 +58,6 @@ unsigned char nvme_io_timeout = 30;
module_param_named(io_timeout, nvme_io_timeout, byte, 0644);
MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O");
-static unsigned char retry_time = 30;
-module_param(retry_time, byte, 0644);
-MODULE_PARM_DESC(retry_time, "time in seconds to retry failed I/O");
-
static unsigned char shutdown_timeout = 5;
module_param(shutdown_timeout, byte, 0644);
MODULE_PARM_DESC(shutdown_timeout, "timeout in seconds for controller shutdown");
@@ -68,6 +65,9 @@ MODULE_PARM_DESC(shutdown_timeout, "timeout in seconds for controller shutdown")
static int nvme_major;
module_param(nvme_major, int, 0);
+static int nvme_char_major;
+module_param(nvme_char_major, int, 0);
+
static int use_threaded_interrupts;
module_param(use_threaded_interrupts, int, 0);
@@ -76,7 +76,8 @@ static LIST_HEAD(dev_list);
static struct task_struct *nvme_thread;
static struct workqueue_struct *nvme_workq;
static wait_queue_head_t nvme_kthread_wait;
-static struct notifier_block nvme_nb;
+
+static struct class *nvme_class;
static void nvme_reset_failed_dev(struct work_struct *ws);
static int nvme_process_cq(struct nvme_queue *nvmeq);
@@ -95,7 +96,6 @@ struct async_cmd_info {
* commands and one for I/O commands).
*/
struct nvme_queue {
- struct llist_node node;
struct device *q_dmadev;
struct nvme_dev *dev;
char irqname[24]; /* nvme4294967295-65535\0 */
@@ -482,6 +482,62 @@ static int nvme_error_status(u16 status)
}
}
+static void nvme_dif_prep(u32 p, u32 v, struct t10_pi_tuple *pi)
+{
+ if (be32_to_cpu(pi->ref_tag) == v)
+ pi->ref_tag = cpu_to_be32(p);
+}
+
+static void nvme_dif_complete(u32 p, u32 v, struct t10_pi_tuple *pi)
+{
+ if (be32_to_cpu(pi->ref_tag) == p)
+ pi->ref_tag = cpu_to_be32(v);
+}
+
+/**
+ * nvme_dif_remap - remaps ref tags to bip seed and physical lba
+ *
+ * The virtual start sector is the one that was originally submitted by the
+ * block layer. Due to partitioning, MD/DM cloning, etc. the actual physical
+ * start sector may be different. Remap protection information to match the
+ * physical LBA on writes, and back to the original seed on reads.
+ *
+ * Type 0 and 3 do not have a ref tag, so no remapping required.
+ */
+static void nvme_dif_remap(struct request *req,
+ void (*dif_swap)(u32 p, u32 v, struct t10_pi_tuple *pi))
+{
+ struct nvme_ns *ns = req->rq_disk->private_data;
+ struct bio_integrity_payload *bip;
+ struct t10_pi_tuple *pi;
+ void *p, *pmap;
+ u32 i, nlb, ts, phys, virt;
+
+ if (!ns->pi_type || ns->pi_type == NVME_NS_DPS_PI_TYPE3)
+ return;
+
+ bip = bio_integrity(req->bio);
+ if (!bip)
+ return;
+
+ pmap = kmap_atomic(bip->bip_vec->bv_page) + bip->bip_vec->bv_offset;
+ if (!pmap)
+ return;
+
+ p = pmap;
+ virt = bip_get_seed(bip);
+ phys = nvme_block_nr(ns, blk_rq_pos(req));
+ nlb = (blk_rq_bytes(req) >> ns->lba_shift);
+ ts = ns->disk->integrity->tuple_size;
+
+ for (i = 0; i < nlb; i++, virt++, phys++) {
+ pi = (struct t10_pi_tuple *)p;
+ dif_swap(phys, virt, pi);
+ p += ts;
+ }
+ kunmap_atomic(pmap);
+}
+
static void req_completion(struct nvme_queue *nvmeq, void *ctx,
struct nvme_completion *cqe)
{
@@ -512,9 +568,16 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
"completing aborted command with status:%04x\n",
status);
- if (iod->nents)
+ if (iod->nents) {
dma_unmap_sg(&nvmeq->dev->pci_dev->dev, iod->sg, iod->nents,
rq_data_dir(req) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ if (blk_integrity_rq(req)) {
+ if (!rq_data_dir(req))
+ nvme_dif_remap(req, nvme_dif_complete);
+ dma_unmap_sg(&nvmeq->dev->pci_dev->dev, iod->meta_sg, 1,
+ rq_data_dir(req) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ }
+ }
nvme_free_iod(nvmeq->dev, iod);
blk_mq_complete_request(req);
@@ -670,6 +733,24 @@ static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod,
cmnd->rw.prp2 = cpu_to_le64(iod->first_dma);
cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
+
+ if (blk_integrity_rq(req)) {
+ cmnd->rw.metadata = cpu_to_le64(sg_dma_address(iod->meta_sg));
+ switch (ns->pi_type) {
+ case NVME_NS_DPS_PI_TYPE3:
+ control |= NVME_RW_PRINFO_PRCHK_GUARD;
+ break;
+ case NVME_NS_DPS_PI_TYPE1:
+ case NVME_NS_DPS_PI_TYPE2:
+ control |= NVME_RW_PRINFO_PRCHK_GUARD |
+ NVME_RW_PRINFO_PRCHK_REF;
+ cmnd->rw.reftag = cpu_to_le32(
+ nvme_block_nr(ns, blk_rq_pos(req)));
+ break;
+ }
+ } else if (ns->ms)
+ control |= NVME_RW_PRINFO_PRACT;
+
cmnd->rw.control = cpu_to_le16(control);
cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
@@ -690,6 +771,19 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_iod *iod;
enum dma_data_direction dma_dir;
+ /*
+ * If formated with metadata, require the block layer provide a buffer
+ * unless this namespace is formated such that the metadata can be
+ * stripped/generated by the controller with PRACT=1.
+ */
+ if (ns->ms && !blk_integrity_rq(req)) {
+ if (!(ns->pi_type && ns->ms == 8)) {
+ req->errors = -EFAULT;
+ blk_mq_complete_request(req);
+ return BLK_MQ_RQ_QUEUE_OK;
+ }
+ }
+
iod = nvme_alloc_iod(req, ns->dev, GFP_ATOMIC);
if (!iod)
return BLK_MQ_RQ_QUEUE_BUSY;
@@ -725,6 +819,21 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
iod->nents, dma_dir);
goto retry_cmd;
}
+ if (blk_integrity_rq(req)) {
+ if (blk_rq_count_integrity_sg(req->q, req->bio) != 1)
+ goto error_cmd;
+
+ sg_init_table(iod->meta_sg, 1);
+ if (blk_rq_map_integrity_sg(
+ req->q, req->bio, iod->meta_sg) != 1)
+ goto error_cmd;
+
+ if (rq_data_dir(req))
+ nvme_dif_remap(req, nvme_dif_prep);
+
+ if (!dma_map_sg(nvmeq->q_dmadev, iod->meta_sg, 1, dma_dir))
+ goto error_cmd;
+ }
}
nvme_set_info(cmd, iod, req_completion);
@@ -817,14 +926,6 @@ static irqreturn_t nvme_irq_check(int irq, void *data)
return IRQ_WAKE_THREAD;
}
-static void nvme_abort_cmd_info(struct nvme_queue *nvmeq, struct nvme_cmd_info *
- cmd_info)
-{
- spin_lock_irq(&nvmeq->q_lock);
- cancel_cmd_info(cmd_info, NULL);
- spin_unlock_irq(&nvmeq->q_lock);
-}
-
struct sync_cmd_info {
struct task_struct *task;
u32 result;
@@ -847,7 +948,6 @@ static void sync_completion(struct nvme_queue *nvmeq, void *ctx,
static int nvme_submit_sync_cmd(struct request *req, struct nvme_command *cmd,
u32 *result, unsigned timeout)
{
- int ret;
struct sync_cmd_info cmdinfo;
struct nvme_cmd_info *cmd_rq = blk_mq_rq_to_pdu(req);
struct nvme_queue *nvmeq = cmd_rq->nvmeq;
@@ -859,29 +959,12 @@ static int nvme_submit_sync_cmd(struct request *req, struct nvme_command *cmd,
nvme_set_info(cmd_rq, &cmdinfo, sync_completion);
- set_current_state(TASK_KILLABLE);
- ret = nvme_submit_cmd(nvmeq, cmd);
- if (ret) {
- nvme_finish_cmd(nvmeq, req->tag, NULL);
- set_current_state(TASK_RUNNING);
- }
- ret = schedule_timeout(timeout);
-
- /*
- * Ensure that sync_completion has either run, or that it will
- * never run.
- */
- nvme_abort_cmd_info(nvmeq, blk_mq_rq_to_pdu(req));
-
- /*
- * We never got the completion
- */
- if (cmdinfo.status == -EINTR)
- return -EINTR;
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ nvme_submit_cmd(nvmeq, cmd);
+ schedule();
if (result)
*result = cmdinfo.result;
-
return cmdinfo.status;
}
@@ -1158,29 +1241,18 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
struct nvme_cmd_info *cmd = blk_mq_rq_to_pdu(req);
struct nvme_queue *nvmeq = cmd->nvmeq;
- /*
- * The aborted req will be completed on receiving the abort req.
- * We enable the timer again. If hit twice, it'll cause a device reset,
- * as the device then is in a faulty state.
- */
- int ret = BLK_EH_RESET_TIMER;
-
dev_warn(nvmeq->q_dmadev, "Timeout I/O %d QID %d\n", req->tag,
nvmeq->qid);
-
spin_lock_irq(&nvmeq->q_lock);
- if (!nvmeq->dev->initialized) {
- /*
- * Force cancelled command frees the request, which requires we
- * return BLK_EH_NOT_HANDLED.
- */
- nvme_cancel_queue_ios(nvmeq->hctx, req, nvmeq, reserved);
- ret = BLK_EH_NOT_HANDLED;
- } else
- nvme_abort_req(req);
+ nvme_abort_req(req);
spin_unlock_irq(&nvmeq->q_lock);
- return ret;
+ /*
+ * The aborted req will be completed on receiving the abort req.
+ * We enable the timer again. If hit twice, it'll cause a device reset,
+ * as the device then is in a faulty state.
+ */
+ return BLK_EH_RESET_TIMER;
}
static void nvme_free_queue(struct nvme_queue *nvmeq)
@@ -1233,7 +1305,6 @@ static void nvme_clear_queue(struct nvme_queue *nvmeq)
struct blk_mq_hw_ctx *hctx = nvmeq->hctx;
spin_lock_irq(&nvmeq->q_lock);
- nvme_process_cq(nvmeq);
if (hctx && hctx->tags)
blk_mq_tag_busy_iter(hctx, nvme_cancel_queue_ios, nvmeq);
spin_unlock_irq(&nvmeq->q_lock);
@@ -1256,7 +1327,10 @@ static void nvme_disable_queue(struct nvme_dev *dev, int qid)
}
if (!qid && dev->admin_q)
blk_mq_freeze_queue_start(dev->admin_q);
- nvme_clear_queue(nvmeq);
+
+ spin_lock_irq(&nvmeq->q_lock);
+ nvme_process_cq(nvmeq);
+ spin_unlock_irq(&nvmeq->q_lock);
}
static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
@@ -1875,13 +1949,61 @@ static int nvme_getgeo(struct block_device *bd, struct hd_geometry *geo)
return 0;
}
+static void nvme_config_discard(struct nvme_ns *ns)
+{
+ u32 logical_block_size = queue_logical_block_size(ns->queue);
+ ns->queue->limits.discard_zeroes_data = 0;
+ ns->queue->limits.discard_alignment = logical_block_size;
+ ns->queue->limits.discard_granularity = logical_block_size;
+ ns->queue->limits.max_discard_sectors = 0xffffffff;
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, ns->queue);
+}
+
+static int nvme_noop_verify(struct blk_integrity_iter *iter)
+{
+ return 0;
+}
+
+static int nvme_noop_generate(struct blk_integrity_iter *iter)
+{
+ return 0;
+}
+
+struct blk_integrity nvme_meta_noop = {
+ .name = "NVME_META_NOOP",
+ .generate_fn = nvme_noop_generate,
+ .verify_fn = nvme_noop_verify,
+};
+
+static void nvme_init_integrity(struct nvme_ns *ns)
+{
+ struct blk_integrity integrity;
+
+ switch (ns->pi_type) {
+ case NVME_NS_DPS_PI_TYPE3:
+ integrity = t10_pi_type3_crc;
+ break;
+ case NVME_NS_DPS_PI_TYPE1:
+ case NVME_NS_DPS_PI_TYPE2:
+ integrity = t10_pi_type1_crc;
+ break;
+ default:
+ integrity = nvme_meta_noop;
+ break;
+ }
+ integrity.tuple_size = ns->ms;
+ blk_integrity_register(ns->disk, &integrity);
+ blk_queue_max_integrity_segments(ns->queue, 1);
+}
+
static int nvme_revalidate_disk(struct gendisk *disk)
{
struct nvme_ns *ns = disk->private_data;
struct nvme_dev *dev = ns->dev;
struct nvme_id_ns *id;
dma_addr_t dma_addr;
- int lbaf;
+ int lbaf, pi_type, old_ms;
+ unsigned short bs;
id = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr,
GFP_KERNEL);
@@ -1890,16 +2012,50 @@ static int nvme_revalidate_disk(struct gendisk *disk)
__func__);
return 0;
}
+ if (nvme_identify(dev, ns->ns_id, 0, dma_addr)) {
+ dev_warn(&dev->pci_dev->dev,
+ "identify failed ns:%d, setting capacity to 0\n",
+ ns->ns_id);
+ memset(id, 0, sizeof(*id));
+ }
- if (nvme_identify(dev, ns->ns_id, 0, dma_addr))
- goto free;
-
- lbaf = id->flbas & 0xf;
+ old_ms = ns->ms;
+ lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
ns->lba_shift = id->lbaf[lbaf].ds;
+ ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
+
+ /*
+ * If identify namespace failed, use default 512 byte block size so
+ * block layer can use before failing read/write for 0 capacity.
+ */
+ if (ns->lba_shift == 0)
+ ns->lba_shift = 9;
+ bs = 1 << ns->lba_shift;
+
+ /* XXX: PI implementation requires metadata equal t10 pi tuple size */
+ pi_type = ns->ms == sizeof(struct t10_pi_tuple) ?
+ id->dps & NVME_NS_DPS_PI_MASK : 0;
+
+ if (disk->integrity && (ns->pi_type != pi_type || ns->ms != old_ms ||
+ bs != queue_logical_block_size(disk->queue) ||
+ (ns->ms && id->flbas & NVME_NS_FLBAS_META_EXT)))
+ blk_integrity_unregister(disk);
+
+ ns->pi_type = pi_type;
+ blk_queue_logical_block_size(ns->queue, bs);
+
+ if (ns->ms && !disk->integrity && (disk->flags & GENHD_FL_UP) &&
+ !(id->flbas & NVME_NS_FLBAS_META_EXT))
+ nvme_init_integrity(ns);
+
+ if (id->ncap == 0 || (ns->ms && !disk->integrity))
+ set_capacity(disk, 0);
+ else
+ set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
+
+ if (dev->oncs & NVME_CTRL_ONCS_DSM)
+ nvme_config_discard(ns);
- blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
- set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
- free:
dma_free_coherent(&dev->pci_dev->dev, 4096, id, dma_addr);
return 0;
}
@@ -1923,8 +2079,7 @@ static int nvme_kthread(void *data)
spin_lock(&dev_list_lock);
list_for_each_entry_safe(dev, next, &dev_list, node) {
int i;
- if (readl(&dev->bar->csts) & NVME_CSTS_CFS &&
- dev->initialized) {
+ if (readl(&dev->bar->csts) & NVME_CSTS_CFS) {
if (work_busy(&dev->reset_work))
continue;
list_del_init(&dev->node);
@@ -1956,30 +2111,16 @@ static int nvme_kthread(void *data)
return 0;
}
-static void nvme_config_discard(struct nvme_ns *ns)
-{
- u32 logical_block_size = queue_logical_block_size(ns->queue);
- ns->queue->limits.discard_zeroes_data = 0;
- ns->queue->limits.discard_alignment = logical_block_size;
- ns->queue->limits.discard_granularity = logical_block_size;
- ns->queue->limits.max_discard_sectors = 0xffffffff;
- queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, ns->queue);
-}
-
-static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
- struct nvme_id_ns *id, struct nvme_lba_range_type *rt)
+static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
{
struct nvme_ns *ns;
struct gendisk *disk;
int node = dev_to_node(&dev->pci_dev->dev);
- int lbaf;
-
- if (rt->attributes & NVME_LBART_ATTRIB_HIDE)
- return NULL;
ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node);
if (!ns)
- return NULL;
+ return;
+
ns->queue = blk_mq_init_queue(&dev->tagset);
if (IS_ERR(ns->queue))
goto out_free_ns;
@@ -1995,9 +2136,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
ns->ns_id = nsid;
ns->disk = disk;
- lbaf = id->flbas & 0xf;
- ns->lba_shift = id->lbaf[lbaf].ds;
- ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
+ ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */
+ list_add_tail(&ns->list, &dev->namespaces);
+
blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
if (dev->max_hw_sectors)
blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
@@ -2011,21 +2152,26 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
disk->fops = &nvme_fops;
disk->private_data = ns;
disk->queue = ns->queue;
- disk->driverfs_dev = &dev->pci_dev->dev;
+ disk->driverfs_dev = dev->device;
disk->flags = GENHD_FL_EXT_DEVT;
sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
- set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
-
- if (dev->oncs & NVME_CTRL_ONCS_DSM)
- nvme_config_discard(ns);
-
- return ns;
+ /*
+ * Initialize capacity to 0 until we establish the namespace format and
+ * setup integrity extentions if necessary. The revalidate_disk after
+ * add_disk allows the driver to register with integrity if the format
+ * requires it.
+ */
+ set_capacity(disk, 0);
+ nvme_revalidate_disk(ns->disk);
+ add_disk(ns->disk);
+ if (ns->ms)
+ revalidate_disk(ns->disk);
+ return;
out_free_queue:
blk_cleanup_queue(ns->queue);
out_free_ns:
kfree(ns);
- return NULL;
}
static void nvme_create_io_queues(struct nvme_dev *dev)
@@ -2150,22 +2296,20 @@ static int nvme_dev_add(struct nvme_dev *dev)
struct pci_dev *pdev = dev->pci_dev;
int res;
unsigned nn, i;
- struct nvme_ns *ns;
struct nvme_id_ctrl *ctrl;
- struct nvme_id_ns *id_ns;
void *mem;
dma_addr_t dma_addr;
int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
- mem = dma_alloc_coherent(&pdev->dev, 8192, &dma_addr, GFP_KERNEL);
+ mem = dma_alloc_coherent(&pdev->dev, 4096, &dma_addr, GFP_KERNEL);
if (!mem)
return -ENOMEM;
res = nvme_identify(dev, 0, 1, dma_addr);
if (res) {
dev_err(&pdev->dev, "Identify Controller failed (%d)\n", res);
- res = -EIO;
- goto out;
+ dma_free_coherent(&dev->pci_dev->dev, 4096, mem, dma_addr);
+ return -EIO;
}
ctrl = mem;
@@ -2191,6 +2335,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
} else
dev->max_hw_sectors = max_hw_sectors;
}
+ dma_free_coherent(&dev->pci_dev->dev, 4096, mem, dma_addr);
dev->tagset.ops = &nvme_mq_ops;
dev->tagset.nr_hw_queues = dev->online_queues - 1;
@@ -2203,33 +2348,12 @@ static int nvme_dev_add(struct nvme_dev *dev)
dev->tagset.driver_data = dev;
if (blk_mq_alloc_tag_set(&dev->tagset))
- goto out;
-
- id_ns = mem;
- for (i = 1; i <= nn; i++) {
- res = nvme_identify(dev, i, 0, dma_addr);
- if (res)
- continue;
-
- if (id_ns->ncap == 0)
- continue;
-
- res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i,
- dma_addr + 4096, NULL);
- if (res)
- memset(mem + 4096, 0, 4096);
+ return 0;
- ns = nvme_alloc_ns(dev, i, mem, mem + 4096);
- if (ns)
- list_add_tail(&ns->list, &dev->namespaces);
- }
- list_for_each_entry(ns, &dev->namespaces, list)
- add_disk(ns->disk);
- res = 0;
+ for (i = 1; i <= nn; i++)
+ nvme_alloc_ns(dev, i);
- out:
- dma_free_coherent(&dev->pci_dev->dev, 8192, mem, dma_addr);
- return res;
+ return 0;
}
static int nvme_dev_map(struct nvme_dev *dev)
@@ -2358,8 +2482,6 @@ static struct nvme_delq_ctx *nvme_get_dq(struct nvme_delq_ctx *dq)
static void nvme_del_queue_end(struct nvme_queue *nvmeq)
{
struct nvme_delq_ctx *dq = nvmeq->cmdinfo.ctx;
-
- nvme_clear_queue(nvmeq);
nvme_put_dq(dq);
}
@@ -2502,7 +2624,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
int i;
u32 csts = -1;
- dev->initialized = 0;
nvme_dev_list_remove(dev);
if (dev->bar) {
@@ -2513,7 +2634,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
for (i = dev->queue_count - 1; i >= 0; i--) {
struct nvme_queue *nvmeq = dev->queues[i];
nvme_suspend_queue(nvmeq);
- nvme_clear_queue(nvmeq);
}
} else {
nvme_disable_io_queues(dev);
@@ -2521,6 +2641,9 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
nvme_disable_queue(dev, 0);
}
nvme_dev_unmap(dev);
+
+ for (i = dev->queue_count - 1; i >= 0; i--)
+ nvme_clear_queue(dev->queues[i]);
}
static void nvme_dev_remove(struct nvme_dev *dev)
@@ -2528,8 +2651,11 @@ static void nvme_dev_remove(struct nvme_dev *dev)
struct nvme_ns *ns;
list_for_each_entry(ns, &dev->namespaces, list) {
- if (ns->disk->flags & GENHD_FL_UP)
+ if (ns->disk->flags & GENHD_FL_UP) {
+ if (ns->disk->integrity)
+ blk_integrity_unregister(ns->disk);
del_gendisk(ns->disk);
+ }
if (!blk_queue_dying(ns->queue)) {
blk_mq_abort_requeue_list(ns->queue);
blk_cleanup_queue(ns->queue);
@@ -2611,6 +2737,7 @@ static void nvme_free_dev(struct kref *kref)
struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
pci_dev_put(dev->pci_dev);
+ put_device(dev->device);
nvme_free_namespaces(dev);
nvme_release_instance(dev);
blk_mq_free_tag_set(&dev->tagset);
@@ -2622,11 +2749,27 @@ static void nvme_free_dev(struct kref *kref)
static int nvme_dev_open(struct inode *inode, struct file *f)
{
- struct nvme_dev *dev = container_of(f->private_data, struct nvme_dev,
- miscdev);
- kref_get(&dev->kref);
- f->private_data = dev;
- return 0;
+ struct nvme_dev *dev;
+ int instance = iminor(inode);
+ int ret = -ENODEV;
+
+ spin_lock(&dev_list_lock);
+ list_for_each_entry(dev, &dev_list, node) {
+ if (dev->instance == instance) {
+ if (!dev->admin_q) {
+ ret = -EWOULDBLOCK;
+ break;
+ }
+ if (!kref_get_unless_zero(&dev->kref))
+ break;
+ f->private_data = dev;
+ ret = 0;
+ break;
+ }
+ }
+ spin_unlock(&dev_list_lock);
+
+ return ret;
}
static int nvme_dev_release(struct inode *inode, struct file *f)
@@ -2768,7 +2911,6 @@ static int nvme_dev_resume(struct nvme_dev *dev)
nvme_unfreeze_queues(dev);
nvme_set_irq_hints(dev);
}
- dev->initialized = 1;
return 0;
}
@@ -2799,6 +2941,7 @@ static void nvme_reset_workfn(struct work_struct *work)
dev->reset_workfn(work);
}
+static void nvme_async_probe(struct work_struct *work);
static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int node, result = -ENOMEM;
@@ -2834,37 +2977,20 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto release;
kref_init(&dev->kref);
- result = nvme_dev_start(dev);
- if (result)
+ dev->device = device_create(nvme_class, &pdev->dev,
+ MKDEV(nvme_char_major, dev->instance),
+ dev, "nvme%d", dev->instance);
+ if (IS_ERR(dev->device)) {
+ result = PTR_ERR(dev->device);
goto release_pools;
+ }
+ get_device(dev->device);
- if (dev->online_queues > 1)
- result = nvme_dev_add(dev);
- if (result)
- goto shutdown;
-
- scnprintf(dev->name, sizeof(dev->name), "nvme%d", dev->instance);
- dev->miscdev.minor = MISC_DYNAMIC_MINOR;
- dev->miscdev.parent = &pdev->dev;
- dev->miscdev.name = dev->name;
- dev->miscdev.fops = &nvme_dev_fops;
- result = misc_register(&dev->miscdev);
- if (result)
- goto remove;
-
- nvme_set_irq_hints(dev);
-
- dev->initialized = 1;
+ INIT_WORK(&dev->probe_work, nvme_async_probe);
+ schedule_work(&dev->probe_work);
return 0;
- remove:
- nvme_dev_remove(dev);
- nvme_dev_remove_admin(dev);
- nvme_free_namespaces(dev);
- shutdown:
- nvme_dev_shutdown(dev);
release_pools:
- nvme_free_queues(dev, 0);
nvme_release_prp_pools(dev);
release:
nvme_release_instance(dev);
@@ -2877,6 +3003,29 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return result;
}
+static void nvme_async_probe(struct work_struct *work)
+{
+ struct nvme_dev *dev = container_of(work, struct nvme_dev, probe_work);
+ int result;
+
+ result = nvme_dev_start(dev);
+ if (result)
+ goto reset;
+
+ if (dev->online_queues > 1)
+ result = nvme_dev_add(dev);
+ if (result)
+ goto reset;
+
+ nvme_set_irq_hints(dev);
+ return;
+ reset:
+ if (!work_busy(&dev->reset_work)) {
+ dev->reset_workfn = nvme_reset_failed_dev;
+ queue_work(nvme_workq, &dev->reset_work);
+ }
+}
+
static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
{
struct nvme_dev *dev = pci_get_drvdata(pdev);
@@ -2902,11 +3051,12 @@ static void nvme_remove(struct pci_dev *pdev)
spin_unlock(&dev_list_lock);
pci_set_drvdata(pdev, NULL);
+ flush_work(&dev->probe_work);
flush_work(&dev->reset_work);
- misc_deregister(&dev->miscdev);
nvme_dev_shutdown(dev);
nvme_dev_remove(dev);
nvme_dev_remove_admin(dev);
+ device_destroy(nvme_class, MKDEV(nvme_char_major, dev->instance));
nvme_free_queues(dev, 0);
nvme_release_prp_pools(dev);
kref_put(&dev->kref, nvme_free_dev);
@@ -2990,11 +3140,26 @@ static int __init nvme_init(void)
else if (result > 0)
nvme_major = result;
+ result = __register_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme",
+ &nvme_dev_fops);
+ if (result < 0)
+ goto unregister_blkdev;
+ else if (result > 0)
+ nvme_char_major = result;
+
+ nvme_class = class_create(THIS_MODULE, "nvme");
+ if (!nvme_class)
+ goto unregister_chrdev;
+
result = pci_register_driver(&nvme_driver);
if (result)
- goto unregister_blkdev;
+ goto destroy_class;
return 0;
+ destroy_class:
+ class_destroy(nvme_class);
+ unregister_chrdev:
+ __unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
unregister_blkdev:
unregister_blkdev(nvme_major, "nvme");
kill_workq:
@@ -3005,9 +3170,10 @@ static int __init nvme_init(void)
static void __exit nvme_exit(void)
{
pci_unregister_driver(&nvme_driver);
- unregister_hotcpu_notifier(&nvme_nb);
unregister_blkdev(nvme_major, "nvme");
destroy_workqueue(nvme_workq);
+ class_destroy(nvme_class);
+ __unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
BUG_ON(nvme_thread && !IS_ERR(nvme_thread));
_nvme_check_size();
}
diff --git a/drivers/block/nvme-scsi.c b/drivers/block/nvme-scsi.c
index 5e78568026c339..e10196e0182d45 100644
--- a/drivers/block/nvme-scsi.c
+++ b/drivers/block/nvme-scsi.c
@@ -779,10 +779,8 @@ static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
struct nvme_dev *dev = ns->dev;
dma_addr_t dma_addr;
void *mem;
- struct nvme_id_ctrl *id_ctrl;
int res = SNTI_TRANSLATION_SUCCESS;
int nvme_sc;
- u8 ieee[4];
int xfer_len;
__be32 tmp_id = cpu_to_be32(ns->ns_id);
@@ -793,46 +791,60 @@ static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
goto out_dma;
}
- /* nvme controller identify */
- nvme_sc = nvme_identify(dev, 0, 1, dma_addr);
- res = nvme_trans_status_code(hdr, nvme_sc);
- if (res)
- goto out_free;
- if (nvme_sc) {
- res = nvme_sc;
- goto out_free;
- }
- id_ctrl = mem;
-
- /* Since SCSI tried to save 4 bits... [SPC-4(r34) Table 591] */
- ieee[0] = id_ctrl->ieee[0] << 4;
- ieee[1] = id_ctrl->ieee[0] >> 4 | id_ctrl->ieee[1] << 4;
- ieee[2] = id_ctrl->ieee[1] >> 4 | id_ctrl->ieee[2] << 4;
- ieee[3] = id_ctrl->ieee[2] >> 4;
-
- memset(inq_response, 0, STANDARD_INQUIRY_LENGTH);
+ memset(inq_response, 0, alloc_len);
inq_response[1] = INQ_DEVICE_IDENTIFICATION_PAGE; /* Page Code */
- inq_response[3] = 20; /* Page Length */
- /* Designation Descriptor start */
- inq_response[4] = 0x01; /* Proto ID=0h | Code set=1h */
- inq_response[5] = 0x03; /* PIV=0b | Asso=00b | Designator Type=3h */
- inq_response[6] = 0x00; /* Rsvd */
- inq_response[7] = 16; /* Designator Length */
- /* Designator start */
- inq_response[8] = 0x60 | ieee[3]; /* NAA=6h | IEEE ID MSB, High nibble*/
- inq_response[9] = ieee[2]; /* IEEE ID */
- inq_response[10] = ieee[1]; /* IEEE ID */
- inq_response[11] = ieee[0]; /* IEEE ID| Vendor Specific ID... */
- inq_response[12] = (dev->pci_dev->vendor & 0xFF00) >> 8;
- inq_response[13] = (dev->pci_dev->vendor & 0x00FF);
- inq_response[14] = dev->serial[0];
- inq_response[15] = dev->serial[1];
- inq_response[16] = dev->model[0];
- inq_response[17] = dev->model[1];
- memcpy(&inq_response[18], &tmp_id, sizeof(u32));
- /* Last 2 bytes are zero */
+ if (readl(&dev->bar->vs) >= NVME_VS(1, 1)) {
+ struct nvme_id_ns *id_ns = mem;
+ void *eui = id_ns->eui64;
+ int len = sizeof(id_ns->eui64);
- xfer_len = min(alloc_len, STANDARD_INQUIRY_LENGTH);
+ nvme_sc = nvme_identify(dev, ns->ns_id, 0, dma_addr);
+ res = nvme_trans_status_code(hdr, nvme_sc);
+ if (res)
+ goto out_free;
+ if (nvme_sc) {
+ res = nvme_sc;
+ goto out_free;
+ }
+
+ if (readl(&dev->bar->vs) >= NVME_VS(1, 2)) {
+ if (bitmap_empty(eui, len * 8)) {
+ eui = id_ns->nguid;
+ len = sizeof(id_ns->nguid);
+ }
+ }
+ if (bitmap_empty(eui, len * 8))
+ goto scsi_string;
+
+ inq_response[3] = 4 + len; /* Page Length */
+ /* Designation Descriptor start */
+ inq_response[4] = 0x01; /* Proto ID=0h | Code set=1h */
+ inq_response[5] = 0x02; /* PIV=0b | Asso=00b | Designator Type=2h */
+ inq_response[6] = 0x00; /* Rsvd */
+ inq_response[7] = len; /* Designator Length */
+ memcpy(&inq_response[8], eui, len);
+ } else {
+ scsi_string:
+ if (alloc_len < 72) {
+ res = nvme_trans_completion(hdr,
+ SAM_STAT_CHECK_CONDITION,
+ ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
+ SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
+ goto out_free;
+ }
+ inq_response[3] = 0x48; /* Page Length */
+ /* Designation Descriptor start */
+ inq_response[4] = 0x03; /* Proto ID=0h | Code set=3h */
+ inq_response[5] = 0x08; /* PIV=0b | Asso=00b | Designator Type=8h */
+ inq_response[6] = 0x00; /* Rsvd */
+ inq_response[7] = 0x44; /* Designator Length */
+
+ sprintf(&inq_response[8], "%04x", dev->pci_dev->vendor);
+ memcpy(&inq_response[12], dev->model, sizeof(dev->model));
+ sprintf(&inq_response[52], "%04x", tmp_id);
+ memcpy(&inq_response[56], dev->serial, sizeof(dev->serial));
+ }
+ xfer_len = alloc_len;
res = nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
out_free:
@@ -1600,7 +1612,7 @@ static inline void nvme_trans_modesel_get_bd_len(u8 *parm_list, u8 cdb10,
/* 10 Byte CDB */
*bd_len = (parm_list[MODE_SELECT_10_BD_OFFSET] << 8) +
parm_list[MODE_SELECT_10_BD_OFFSET + 1];
- *llbaa = parm_list[MODE_SELECT_10_LLBAA_OFFSET] &&
+ *llbaa = parm_list[MODE_SELECT_10_LLBAA_OFFSET] &
MODE_SELECT_10_LLBAA_MASK;
} else {
/* 6 Byte CDB */
@@ -2222,7 +2234,7 @@ static int nvme_trans_inquiry(struct nvme_ns *ns, struct sg_io_hdr *hdr,
page_code = GET_INQ_PAGE_CODE(cmd);
alloc_len = GET_INQ_ALLOC_LENGTH(cmd);
- inq_response = kmalloc(STANDARD_INQUIRY_LENGTH, GFP_KERNEL);
+ inq_response = kmalloc(alloc_len, GFP_KERNEL);
if (inq_response == NULL) {
res = -ENOMEM;
goto out_mem;
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index ec318bf434a6c3..1786574536b21e 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -157,12 +157,16 @@ static int ipmi_release(struct inode *inode, struct file *file)
{
struct ipmi_file_private *priv = file->private_data;
int rv;
+ struct ipmi_recv_msg *msg, *next;
rv = ipmi_destroy_user(priv->user);
if (rv)
return rv;
- /* FIXME - free the messages in the list. */
+ list_for_each_entry_safe(msg, next, &priv->recv_msgs, link)
+ ipmi_free_recv_msg(msg);
+
+
kfree(priv);
return 0;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 6b65fa4e0c5586..9bb592872532b1 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -1483,14 +1483,10 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg,
smi_msg->msgid = msgid;
}
-static void smi_send(ipmi_smi_t intf, struct ipmi_smi_handlers *handlers,
- struct ipmi_smi_msg *smi_msg, int priority)
+static struct ipmi_smi_msg *smi_add_send_msg(ipmi_smi_t intf,
+ struct ipmi_smi_msg *smi_msg,
+ int priority)
{
- int run_to_completion = intf->run_to_completion;
- unsigned long flags;
-
- if (!run_to_completion)
- spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
if (intf->curr_msg) {
if (priority > 0)
list_add_tail(&smi_msg->link, &intf->hp_xmit_msgs);
@@ -1500,8 +1496,25 @@ static void smi_send(ipmi_smi_t intf, struct ipmi_smi_handlers *handlers,
} else {
intf->curr_msg = smi_msg;
}
- if (!run_to_completion)
+
+ return smi_msg;
+}
+
+
+static void smi_send(ipmi_smi_t intf, struct ipmi_smi_handlers *handlers,
+ struct ipmi_smi_msg *smi_msg, int priority)
+{
+ int run_to_completion = intf->run_to_completion;
+
+ if (run_to_completion) {
+ smi_msg = smi_add_send_msg(intf, smi_msg, priority);
+ } else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+ smi_msg = smi_add_send_msg(intf, smi_msg, priority);
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+ }
if (smi_msg)
handlers->sender(intf->send_info, smi_msg);
@@ -1985,7 +1998,9 @@ static int smi_ipmb_proc_show(struct seq_file *m, void *v)
seq_printf(m, "%x", intf->channels[0].address);
for (i = 1; i < IPMI_MAX_CHANNELS; i++)
seq_printf(m, " %x", intf->channels[i].address);
- return seq_putc(m, '\n');
+ seq_putc(m, '\n');
+
+ return seq_has_overflowed(m);
}
static int smi_ipmb_proc_open(struct inode *inode, struct file *file)
@@ -2004,9 +2019,11 @@ static int smi_version_proc_show(struct seq_file *m, void *v)
{
ipmi_smi_t intf = m->private;
- return seq_printf(m, "%u.%u\n",
- ipmi_version_major(&intf->bmc->id),
- ipmi_version_minor(&intf->bmc->id));
+ seq_printf(m, "%u.%u\n",
+ ipmi_version_major(&intf->bmc->id),
+ ipmi_version_minor(&intf->bmc->id));
+
+ return seq_has_overflowed(m);
}
static int smi_version_proc_open(struct inode *inode, struct file *file)
@@ -2353,11 +2370,28 @@ static struct attribute *bmc_dev_attrs[] = {
&dev_attr_additional_device_support.attr,
&dev_attr_manufacturer_id.attr,
&dev_attr_product_id.attr,
+ &dev_attr_aux_firmware_revision.attr,
+ &dev_attr_guid.attr,
NULL
};
+static umode_t bmc_dev_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int idx)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct bmc_device *bmc = to_bmc_device(dev);
+ umode_t mode = attr->mode;
+
+ if (attr == &dev_attr_aux_firmware_revision.attr)
+ return bmc->id.aux_firmware_revision_set ? mode : 0;
+ if (attr == &dev_attr_guid.attr)
+ return bmc->guid_set ? mode : 0;
+ return mode;
+}
+
static struct attribute_group bmc_dev_attr_group = {
.attrs = bmc_dev_attrs,
+ .is_visible = bmc_dev_attr_is_visible,
};
static const struct attribute_group *bmc_dev_attr_groups[] = {
@@ -2380,13 +2414,6 @@ cleanup_bmc_device(struct kref *ref)
{
struct bmc_device *bmc = container_of(ref, struct bmc_device, usecount);
- if (bmc->id.aux_firmware_revision_set)
- device_remove_file(&bmc->pdev.dev,
- &dev_attr_aux_firmware_revision);
- if (bmc->guid_set)
- device_remove_file(&bmc->pdev.dev,
- &dev_attr_guid);
-
platform_device_unregister(&bmc->pdev);
}
@@ -2407,33 +2434,6 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf)
mutex_unlock(&ipmidriver_mutex);
}
-static int create_bmc_files(struct bmc_device *bmc)
-{
- int err;
-
- if (bmc->id.aux_firmware_revision_set) {
- err = device_create_file(&bmc->pdev.dev,
- &dev_attr_aux_firmware_revision);
- if (err)
- goto out;
- }
- if (bmc->guid_set) {
- err = device_create_file(&bmc->pdev.dev,
- &dev_attr_guid);
- if (err)
- goto out_aux_firm;
- }
-
- return 0;
-
-out_aux_firm:
- if (bmc->id.aux_firmware_revision_set)
- device_remove_file(&bmc->pdev.dev,
- &dev_attr_aux_firmware_revision);
-out:
- return err;
-}
-
static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum)
{
int rv;
@@ -2522,15 +2522,6 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum)
return rv;
}
- rv = create_bmc_files(bmc);
- if (rv) {
- mutex_lock(&ipmidriver_mutex);
- platform_device_unregister(&bmc->pdev);
- mutex_unlock(&ipmidriver_mutex);
-
- return rv;
- }
-
dev_info(intf->si_dev, "Found new BMC (man_id: 0x%6.6x, "
"prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n",
bmc->id.manufacturer_id,
@@ -4212,7 +4203,6 @@ static void need_waiter(ipmi_smi_t intf)
static atomic_t smi_msg_inuse_count = ATOMIC_INIT(0);
static atomic_t recv_msg_inuse_count = ATOMIC_INIT(0);
-/* FIXME - convert these to slabs. */
static void free_smi_msg(struct ipmi_smi_msg *msg)
{
atomic_dec(&smi_msg_inuse_count);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 967b73aa4e66d3..f6646ed3047e09 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -321,6 +321,18 @@ static int try_smi_init(struct smi_info *smi);
static void cleanup_one_si(struct smi_info *to_clean);
static void cleanup_ipmi_si(void);
+#ifdef DEBUG_TIMING
+void debug_timestamp(char *msg)
+{
+ struct timespec64 t;
+
+ getnstimeofday64(&t);
+ pr_debug("**%s: %lld.%9.9ld\n", msg, (long long) t.tv_sec, t.tv_nsec);
+}
+#else
+#define debug_timestamp(x)
+#endif
+
static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
static int register_xaction_notifier(struct notifier_block *nb)
{
@@ -358,9 +370,6 @@ static void return_hosed_msg(struct smi_info *smi_info, int cCode)
static enum si_sm_result start_next_msg(struct smi_info *smi_info)
{
int rv;
-#ifdef DEBUG_TIMING
- struct timeval t;
-#endif
if (!smi_info->waiting_msg) {
smi_info->curr_msg = NULL;
@@ -370,10 +379,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
smi_info->curr_msg = smi_info->waiting_msg;
smi_info->waiting_msg = NULL;
-#ifdef DEBUG_TIMING
- do_gettimeofday(&t);
- printk(KERN_DEBUG "**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
-#endif
+ debug_timestamp("Start2");
err = atomic_notifier_call_chain(&xaction_notifier_list,
0, smi_info);
if (err & NOTIFY_STOP_MASK) {
@@ -582,12 +588,8 @@ static void check_bt_irq(struct smi_info *smi_info, bool irq_on)
static void handle_transaction_done(struct smi_info *smi_info)
{
struct ipmi_smi_msg *msg;
-#ifdef DEBUG_TIMING
- struct timeval t;
- do_gettimeofday(&t);
- printk(KERN_DEBUG "**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
-#endif
+ debug_timestamp("Done");
switch (smi_info->si_state) {
case SI_NORMAL:
if (!smi_info->curr_msg)
@@ -929,24 +931,15 @@ static void sender(void *send_info,
struct smi_info *smi_info = send_info;
enum si_sm_result result;
unsigned long flags;
-#ifdef DEBUG_TIMING
- struct timeval t;
-#endif
-
- BUG_ON(smi_info->waiting_msg);
- smi_info->waiting_msg = msg;
-#ifdef DEBUG_TIMING
- do_gettimeofday(&t);
- printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
-#endif
+ debug_timestamp("Enqueue");
if (smi_info->run_to_completion) {
/*
* If we are running to completion, start it and run
* transactions until everything is clear.
*/
- smi_info->curr_msg = smi_info->waiting_msg;
+ smi_info->curr_msg = msg;
smi_info->waiting_msg = NULL;
/*
@@ -964,6 +957,15 @@ static void sender(void *send_info,
}
spin_lock_irqsave(&smi_info->si_lock, flags);
+ /*
+ * The following two lines don't need to be under the lock for
+ * the lock's sake, but they do need SMP memory barriers to
+ * avoid getting things out of order. We are already claiming
+ * the lock, anyway, so just do it under the lock to avoid the
+ * ordering problem.
+ */
+ BUG_ON(smi_info->waiting_msg);
+ smi_info->waiting_msg = msg;
check_start_timer_thread(smi_info);
spin_unlock_irqrestore(&smi_info->si_lock, flags);
}
@@ -989,18 +991,18 @@ static void set_run_to_completion(void *send_info, bool i_run_to_completion)
* we are spinning in kipmid looking for something and not delaying
* between checks
*/
-static inline void ipmi_si_set_not_busy(struct timespec *ts)
+static inline void ipmi_si_set_not_busy(struct timespec64 *ts)
{
ts->tv_nsec = -1;
}
-static inline int ipmi_si_is_busy(struct timespec *ts)
+static inline int ipmi_si_is_busy(struct timespec64 *ts)
{
return ts->tv_nsec != -1;
}
static inline int ipmi_thread_busy_wait(enum si_sm_result smi_result,
const struct smi_info *smi_info,
- struct timespec *busy_until)
+ struct timespec64 *busy_until)
{
unsigned int max_busy_us = 0;
@@ -1009,12 +1011,13 @@ static inline int ipmi_thread_busy_wait(enum si_sm_result smi_result,
if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY)
ipmi_si_set_not_busy(busy_until);
else if (!ipmi_si_is_busy(busy_until)) {
- getnstimeofday(busy_until);
- timespec_add_ns(busy_until, max_busy_us*NSEC_PER_USEC);
+ getnstimeofday64(busy_until);
+ timespec64_add_ns(busy_until, max_busy_us*NSEC_PER_USEC);
} else {
- struct timespec now;
- getnstimeofday(&now);
- if (unlikely(timespec_compare(&now, busy_until) > 0)) {
+ struct timespec64 now;
+
+ getnstimeofday64(&now);
+ if (unlikely(timespec64_compare(&now, busy_until) > 0)) {
ipmi_si_set_not_busy(busy_until);
return 0;
}
@@ -1037,7 +1040,7 @@ static int ipmi_thread(void *data)
struct smi_info *smi_info = data;
unsigned long flags;
enum si_sm_result smi_result;
- struct timespec busy_until;
+ struct timespec64 busy_until;
ipmi_si_set_not_busy(&busy_until);
set_user_nice(current, MAX_NICE);
@@ -1128,15 +1131,10 @@ static void smi_timeout(unsigned long data)
unsigned long jiffies_now;
long time_diff;
long timeout;
-#ifdef DEBUG_TIMING
- struct timeval t;
-#endif
spin_lock_irqsave(&(smi_info->si_lock), flags);
-#ifdef DEBUG_TIMING
- do_gettimeofday(&t);
- printk(KERN_DEBUG "**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
-#endif
+ debug_timestamp("Timer");
+
jiffies_now = jiffies;
time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
* SI_USEC_PER_JIFFY);
@@ -1173,18 +1171,13 @@ static irqreturn_t si_irq_handler(int irq, void *data)
{
struct smi_info *smi_info = data;
unsigned long flags;
-#ifdef DEBUG_TIMING
- struct timeval t;
-#endif
spin_lock_irqsave(&(smi_info->si_lock), flags);
smi_inc_stat(smi_info, interrupts);
-#ifdef DEBUG_TIMING
- do_gettimeofday(&t);
- printk(KERN_DEBUG "**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
-#endif
+ debug_timestamp("Interrupt");
+
smi_event_handler(smi_info, 0);
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
return IRQ_HANDLED;
@@ -2038,18 +2031,13 @@ static u32 ipmi_acpi_gpe(acpi_handle gpe_device,
{
struct smi_info *smi_info = context;
unsigned long flags;
-#ifdef DEBUG_TIMING
- struct timeval t;
-#endif
spin_lock_irqsave(&(smi_info->si_lock), flags);
smi_inc_stat(smi_info, interrupts);
-#ifdef DEBUG_TIMING
- do_gettimeofday(&t);
- printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec);
-#endif
+ debug_timestamp("ACPI_GPE");
+
smi_event_handler(smi_info, 0);
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
@@ -2071,7 +2059,6 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
if (!info->irq)
return 0;
- /* FIXME - is level triggered right? */
status = acpi_install_gpe_handler(NULL,
info->irq,
ACPI_GPE_LEVEL_TRIGGERED,
@@ -2998,7 +2985,9 @@ static int smi_type_proc_show(struct seq_file *m, void *v)
{
struct smi_info *smi = m->private;
- return seq_printf(m, "%s\n", si_to_str[smi->si_type]);
+ seq_printf(m, "%s\n", si_to_str[smi->si_type]);
+
+ return seq_has_overflowed(m);
}
static int smi_type_proc_open(struct inode *inode, struct file *file)
@@ -3060,16 +3049,18 @@ static int smi_params_proc_show(struct seq_file *m, void *v)
{
struct smi_info *smi = m->private;
- return seq_printf(m,
- "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n",
- si_to_str[smi->si_type],
- addr_space_to_str[smi->io.addr_type],
- smi->io.addr_data,
- smi->io.regspacing,
- smi->io.regsize,
- smi->io.regshift,
- smi->irq,
- smi->slave_addr);
+ seq_printf(m,
+ "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n",
+ si_to_str[smi->si_type],
+ addr_space_to_str[smi->io.addr_type],
+ smi->io.addr_data,
+ smi->io.regspacing,
+ smi->io.regsize,
+ smi->io.regshift,
+ smi->irq,
+ smi->slave_addr);
+
+ return seq_has_overflowed(m);
}
static int smi_params_proc_open(struct inode *inode, struct file *file)
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 982b96323f823b..f6e378dac5f5b1 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -1097,8 +1097,6 @@ static int ssif_remove(struct i2c_client *client)
if (!ssif_info)
return 0;
- i2c_set_clientdata(client, NULL);
-
/*
* After this point, we won't deliver anything asychronously
* to the message handler. We can unregister ourself.
@@ -1198,7 +1196,9 @@ static int ssif_detect(struct i2c_client *client, struct i2c_board_info *info)
static int smi_type_proc_show(struct seq_file *m, void *v)
{
- return seq_puts(m, "ssif\n");
+ seq_puts(m, "ssif\n");
+
+ return seq_has_overflowed(m);
}
static int smi_type_proc_open(struct inode *inode, struct file *file)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 91f86131bb7aa6..0b474a04730fe4 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -102,12 +102,12 @@ config COMMON_CLK_AXI_CLKGEN
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
FPGAs. It is commonly used in Analog Devices' reference designs.
-config CLK_PPC_CORENET
- bool "Clock driver for PowerPC corenet platforms"
- depends on PPC_E500MC && OF
+config CLK_QORIQ
+ bool "Clock driver for Freescale QorIQ platforms"
+ depends on (PPC_E500MC || ARM) && OF
---help---
- This adds the clock driver support for Freescale PowerPC corenet
- platforms using common clock framework.
+ This adds the clock driver support for Freescale QorIQ platforms
+ using common clock framework.
config COMMON_CLK_XGENE
bool "Clock driver for APM XGene SoC"
@@ -135,6 +135,14 @@ config COMMON_CLK_PXA
---help---
Sypport for the Marvell PXA SoC.
+config COMMON_CLK_CDCE706
+ tristate "Clock driver for TI CDCE706 clock synthesizer"
+ depends on I2C
+ select REGMAP_I2C
+ select RATIONAL
+ ---help---
+ This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
+
source "drivers/clk/qcom/Kconfig"
endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5bc6e1bc1..d478ceb69c5fc6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -16,9 +16,11 @@ endif
# hardware specific clock types
# please keep this section sorted lexicographically by file/directory path name
+obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
+obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
@@ -30,7 +32,7 @@ obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
-obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
+obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index bbdb1b985c9146..86c8a073dcc32a 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -56,6 +56,8 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
static long clk_programmable_determine_rate(struct clk_hw *hw,
unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_hw)
{
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index 1c06f6f3a8c599..05abae89262e20 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1032,6 +1032,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
}
static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate, struct clk_hw **best_parent)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c
new file mode 100644
index 00000000000000..88f4ff6916fe72
--- /dev/null
+++ b/drivers/clk/clk-asm9260.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2014 Oleksij Rempel .
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define HW_AHBCLKCTRL0 0x0020
+#define HW_AHBCLKCTRL1 0x0030
+#define HW_SYSPLLCTRL 0x0100
+#define HW_MAINCLKSEL 0x0120
+#define HW_MAINCLKUEN 0x0124
+#define HW_UARTCLKSEL 0x0128
+#define HW_UARTCLKUEN 0x012c
+#define HW_I2S0CLKSEL 0x0130
+#define HW_I2S0CLKUEN 0x0134
+#define HW_I2S1CLKSEL 0x0138
+#define HW_I2S1CLKUEN 0x013c
+#define HW_WDTCLKSEL 0x0160
+#define HW_WDTCLKUEN 0x0164
+#define HW_CLKOUTCLKSEL 0x0170
+#define HW_CLKOUTCLKUEN 0x0174
+#define HW_CPUCLKDIV 0x017c
+#define HW_SYSAHBCLKDIV 0x0180
+#define HW_I2S0MCLKDIV 0x0190
+#define HW_I2S0SCLKDIV 0x0194
+#define HW_I2S1MCLKDIV 0x0188
+#define HW_I2S1SCLKDIV 0x018c
+#define HW_UART0CLKDIV 0x0198
+#define HW_UART1CLKDIV 0x019c
+#define HW_UART2CLKDIV 0x01a0
+#define HW_UART3CLKDIV 0x01a4
+#define HW_UART4CLKDIV 0x01a8
+#define HW_UART5CLKDIV 0x01ac
+#define HW_UART6CLKDIV 0x01b0
+#define HW_UART7CLKDIV 0x01b4
+#define HW_UART8CLKDIV 0x01b8
+#define HW_UART9CLKDIV 0x01bc
+#define HW_SPI0CLKDIV 0x01c0
+#define HW_SPI1CLKDIV 0x01c4
+#define HW_QUADSPICLKDIV 0x01c8
+#define HW_SSP0CLKDIV 0x01d0
+#define HW_NANDCLKDIV 0x01d4
+#define HW_TRACECLKDIV 0x01e0
+#define HW_CAMMCLKDIV 0x01e8
+#define HW_WDTCLKDIV 0x01ec
+#define HW_CLKOUTCLKDIV 0x01f4
+#define HW_MACCLKDIV 0x01f8
+#define HW_LCDCLKDIV 0x01fc
+#define HW_ADCANACLKDIV 0x0200
+
+static struct clk *clks[MAX_CLKS];
+static struct clk_onecell_data clk_data;
+static DEFINE_SPINLOCK(asm9260_clk_lock);
+
+struct asm9260_div_clk {
+ unsigned int idx;
+ const char *name;
+ const char *parent_name;
+ u32 reg;
+};
+
+struct asm9260_gate_data {
+ unsigned int idx;
+ const char *name;
+ const char *parent_name;
+ u32 reg;
+ u8 bit_idx;
+ unsigned long flags;
+};
+
+struct asm9260_mux_clock {
+ u8 mask;
+ u32 *table;
+ const char *name;
+ const char **parent_names;
+ u8 num_parents;
+ unsigned long offset;
+ unsigned long flags;
+};
+
+static void __iomem *base;
+
+static const struct asm9260_div_clk asm9260_div_clks[] __initconst = {
+ { CLKID_SYS_CPU, "cpu_div", "main_gate", HW_CPUCLKDIV },
+ { CLKID_SYS_AHB, "ahb_div", "cpu_div", HW_SYSAHBCLKDIV },
+
+ /* i2s has two deviders: one for only external mclk and internal
+ * devider for all clks. */
+ { CLKID_SYS_I2S0M, "i2s0m_div", "i2s0_mclk", HW_I2S0MCLKDIV },
+ { CLKID_SYS_I2S1M, "i2s1m_div", "i2s1_mclk", HW_I2S1MCLKDIV },
+ { CLKID_SYS_I2S0S, "i2s0s_div", "i2s0_gate", HW_I2S0SCLKDIV },
+ { CLKID_SYS_I2S1S, "i2s1s_div", "i2s0_gate", HW_I2S1SCLKDIV },
+
+ { CLKID_SYS_UART0, "uart0_div", "uart_gate", HW_UART0CLKDIV },
+ { CLKID_SYS_UART1, "uart1_div", "uart_gate", HW_UART1CLKDIV },
+ { CLKID_SYS_UART2, "uart2_div", "uart_gate", HW_UART2CLKDIV },
+ { CLKID_SYS_UART3, "uart3_div", "uart_gate", HW_UART3CLKDIV },
+ { CLKID_SYS_UART4, "uart4_div", "uart_gate", HW_UART4CLKDIV },
+ { CLKID_SYS_UART5, "uart5_div", "uart_gate", HW_UART5CLKDIV },
+ { CLKID_SYS_UART6, "uart6_div", "uart_gate", HW_UART6CLKDIV },
+ { CLKID_SYS_UART7, "uart7_div", "uart_gate", HW_UART7CLKDIV },
+ { CLKID_SYS_UART8, "uart8_div", "uart_gate", HW_UART8CLKDIV },
+ { CLKID_SYS_UART9, "uart9_div", "uart_gate", HW_UART9CLKDIV },
+
+ { CLKID_SYS_SPI0, "spi0_div", "main_gate", HW_SPI0CLKDIV },
+ { CLKID_SYS_SPI1, "spi1_div", "main_gate", HW_SPI1CLKDIV },
+ { CLKID_SYS_QUADSPI, "quadspi_div", "main_gate", HW_QUADSPICLKDIV },
+ { CLKID_SYS_SSP0, "ssp0_div", "main_gate", HW_SSP0CLKDIV },
+ { CLKID_SYS_NAND, "nand_div", "main_gate", HW_NANDCLKDIV },
+ { CLKID_SYS_TRACE, "trace_div", "main_gate", HW_TRACECLKDIV },
+ { CLKID_SYS_CAMM, "camm_div", "main_gate", HW_CAMMCLKDIV },
+ { CLKID_SYS_MAC, "mac_div", "main_gate", HW_MACCLKDIV },
+ { CLKID_SYS_LCD, "lcd_div", "main_gate", HW_LCDCLKDIV },
+ { CLKID_SYS_ADCANA, "adcana_div", "main_gate", HW_ADCANACLKDIV },
+
+ { CLKID_SYS_WDT, "wdt_div", "wdt_gate", HW_WDTCLKDIV },
+ { CLKID_SYS_CLKOUT, "clkout_div", "clkout_gate", HW_CLKOUTCLKDIV },
+};
+
+static const struct asm9260_gate_data asm9260_mux_gates[] __initconst = {
+ { 0, "main_gate", "main_mux", HW_MAINCLKUEN, 0 },
+ { 0, "uart_gate", "uart_mux", HW_UARTCLKUEN, 0 },
+ { 0, "i2s0_gate", "i2s0_mux", HW_I2S0CLKUEN, 0 },
+ { 0, "i2s1_gate", "i2s1_mux", HW_I2S1CLKUEN, 0 },
+ { 0, "wdt_gate", "wdt_mux", HW_WDTCLKUEN, 0 },
+ { 0, "clkout_gate", "clkout_mux", HW_CLKOUTCLKUEN, 0 },
+};
+static const struct asm9260_gate_data asm9260_ahb_gates[] __initconst = {
+ /* ahb gates */
+ { CLKID_AHB_ROM, "rom", "ahb_div",
+ HW_AHBCLKCTRL0, 1, CLK_IGNORE_UNUSED},
+ { CLKID_AHB_RAM, "ram", "ahb_div",
+ HW_AHBCLKCTRL0, 2, CLK_IGNORE_UNUSED},
+ { CLKID_AHB_GPIO, "gpio", "ahb_div",
+ HW_AHBCLKCTRL0, 4 },
+ { CLKID_AHB_MAC, "mac", "ahb_div",
+ HW_AHBCLKCTRL0, 5 },
+ { CLKID_AHB_EMI, "emi", "ahb_div",
+ HW_AHBCLKCTRL0, 6, CLK_IGNORE_UNUSED},
+ { CLKID_AHB_USB0, "usb0", "ahb_div",
+ HW_AHBCLKCTRL0, 7 },
+ { CLKID_AHB_USB1, "usb1", "ahb_div",
+ HW_AHBCLKCTRL0, 8 },
+ { CLKID_AHB_DMA0, "dma0", "ahb_div",
+ HW_AHBCLKCTRL0, 9 },
+ { CLKID_AHB_DMA1, "dma1", "ahb_div",
+ HW_AHBCLKCTRL0, 10 },
+ { CLKID_AHB_UART0, "uart0", "ahb_div",
+ HW_AHBCLKCTRL0, 11 },
+ { CLKID_AHB_UART1, "uart1", "ahb_div",
+ HW_AHBCLKCTRL0, 12 },
+ { CLKID_AHB_UART2, "uart2", "ahb_div",
+ HW_AHBCLKCTRL0, 13 },
+ { CLKID_AHB_UART3, "uart3", "ahb_div",
+ HW_AHBCLKCTRL0, 14 },
+ { CLKID_AHB_UART4, "uart4", "ahb_div",
+ HW_AHBCLKCTRL0, 15 },
+ { CLKID_AHB_UART5, "uart5", "ahb_div",
+ HW_AHBCLKCTRL0, 16 },
+ { CLKID_AHB_UART6, "uart6", "ahb_div",
+ HW_AHBCLKCTRL0, 17 },
+ { CLKID_AHB_UART7, "uart7", "ahb_div",
+ HW_AHBCLKCTRL0, 18 },
+ { CLKID_AHB_UART8, "uart8", "ahb_div",
+ HW_AHBCLKCTRL0, 19 },
+ { CLKID_AHB_UART9, "uart9", "ahb_div",
+ HW_AHBCLKCTRL0, 20 },
+ { CLKID_AHB_I2S0, "i2s0", "ahb_div",
+ HW_AHBCLKCTRL0, 21 },
+ { CLKID_AHB_I2C0, "i2c0", "ahb_div",
+ HW_AHBCLKCTRL0, 22 },
+ { CLKID_AHB_I2C1, "i2c1", "ahb_div",
+ HW_AHBCLKCTRL0, 23 },
+ { CLKID_AHB_SSP0, "ssp0", "ahb_div",
+ HW_AHBCLKCTRL0, 24 },
+ { CLKID_AHB_IOCONFIG, "ioconf", "ahb_div",
+ HW_AHBCLKCTRL0, 25 },
+ { CLKID_AHB_WDT, "wdt", "ahb_div",
+ HW_AHBCLKCTRL0, 26 },
+ { CLKID_AHB_CAN0, "can0", "ahb_div",
+ HW_AHBCLKCTRL0, 27 },
+ { CLKID_AHB_CAN1, "can1", "ahb_div",
+ HW_AHBCLKCTRL0, 28 },
+ { CLKID_AHB_MPWM, "mpwm", "ahb_div",
+ HW_AHBCLKCTRL0, 29 },
+ { CLKID_AHB_SPI0, "spi0", "ahb_div",
+ HW_AHBCLKCTRL0, 30 },
+ { CLKID_AHB_SPI1, "spi1", "ahb_div",
+ HW_AHBCLKCTRL0, 31 },
+
+ { CLKID_AHB_QEI, "qei", "ahb_div",
+ HW_AHBCLKCTRL1, 0 },
+ { CLKID_AHB_QUADSPI0, "quadspi0", "ahb_div",
+ HW_AHBCLKCTRL1, 1 },
+ { CLKID_AHB_CAMIF, "capmif", "ahb_div",
+ HW_AHBCLKCTRL1, 2 },
+ { CLKID_AHB_LCDIF, "lcdif", "ahb_div",
+ HW_AHBCLKCTRL1, 3 },
+ { CLKID_AHB_TIMER0, "timer0", "ahb_div",
+ HW_AHBCLKCTRL1, 4 },
+ { CLKID_AHB_TIMER1, "timer1", "ahb_div",
+ HW_AHBCLKCTRL1, 5 },
+ { CLKID_AHB_TIMER2, "timer2", "ahb_div",
+ HW_AHBCLKCTRL1, 6 },
+ { CLKID_AHB_TIMER3, "timer3", "ahb_div",
+ HW_AHBCLKCTRL1, 7 },
+ { CLKID_AHB_IRQ, "irq", "ahb_div",
+ HW_AHBCLKCTRL1, 8, CLK_IGNORE_UNUSED},
+ { CLKID_AHB_RTC, "rtc", "ahb_div",
+ HW_AHBCLKCTRL1, 9 },
+ { CLKID_AHB_NAND, "nand", "ahb_div",
+ HW_AHBCLKCTRL1, 10 },
+ { CLKID_AHB_ADC0, "adc0", "ahb_div",
+ HW_AHBCLKCTRL1, 11 },
+ { CLKID_AHB_LED, "led", "ahb_div",
+ HW_AHBCLKCTRL1, 12 },
+ { CLKID_AHB_DAC0, "dac0", "ahb_div",
+ HW_AHBCLKCTRL1, 13 },
+ { CLKID_AHB_LCD, "lcd", "ahb_div",
+ HW_AHBCLKCTRL1, 14 },
+ { CLKID_AHB_I2S1, "i2s1", "ahb_div",
+ HW_AHBCLKCTRL1, 15 },
+ { CLKID_AHB_MAC1, "mac1", "ahb_div",
+ HW_AHBCLKCTRL1, 16 },
+};
+
+static const char __initdata *main_mux_p[] = { NULL, NULL };
+static const char __initdata *i2s0_mux_p[] = { NULL, NULL, "i2s0m_div"};
+static const char __initdata *i2s1_mux_p[] = { NULL, NULL, "i2s1m_div"};
+static const char __initdata *clkout_mux_p[] = { NULL, NULL, "rtc"};
+static u32 three_mux_table[] = {0, 1, 3};
+
+static struct asm9260_mux_clock asm9260_mux_clks[] __initdata = {
+ { 1, three_mux_table, "main_mux", main_mux_p,
+ ARRAY_SIZE(main_mux_p), HW_MAINCLKSEL, },
+ { 1, three_mux_table, "uart_mux", main_mux_p,
+ ARRAY_SIZE(main_mux_p), HW_UARTCLKSEL, },
+ { 1, three_mux_table, "wdt_mux", main_mux_p,
+ ARRAY_SIZE(main_mux_p), HW_WDTCLKSEL, },
+ { 3, three_mux_table, "i2s0_mux", i2s0_mux_p,
+ ARRAY_SIZE(i2s0_mux_p), HW_I2S0CLKSEL, },
+ { 3, three_mux_table, "i2s1_mux", i2s1_mux_p,
+ ARRAY_SIZE(i2s1_mux_p), HW_I2S1CLKSEL, },
+ { 3, three_mux_table, "clkout_mux", clkout_mux_p,
+ ARRAY_SIZE(clkout_mux_p), HW_CLKOUTCLKSEL, },
+};
+
+static void __init asm9260_acc_init(struct device_node *np)
+{
+ struct clk *clk;
+ const char *ref_clk, *pll_clk = "pll";
+ u32 rate;
+ int n;
+ u32 accuracy = 0;
+
+ base = of_io_request_and_map(np, 0, np->name);
+ if (!base)
+ panic("%s: unable to map resource", np->name);
+
+ /* register pll */
+ rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000;
+
+ ref_clk = of_clk_get_parent_name(np, 0);
+ accuracy = clk_get_accuracy(__clk_lookup(ref_clk));
+ clk = clk_register_fixed_rate_with_accuracy(NULL, pll_clk,
+ ref_clk, 0, rate, accuracy);
+
+ if (IS_ERR(clk))
+ panic("%s: can't register REFCLK. Check DT!", np->name);
+
+ for (n = 0; n < ARRAY_SIZE(asm9260_mux_clks); n++) {
+ const struct asm9260_mux_clock *mc = &asm9260_mux_clks[n];
+
+ mc->parent_names[0] = ref_clk;
+ mc->parent_names[1] = pll_clk;
+ clk = clk_register_mux_table(NULL, mc->name, mc->parent_names,
+ mc->num_parents, mc->flags, base + mc->offset,
+ 0, mc->mask, 0, mc->table, &asm9260_clk_lock);
+ }
+
+ /* clock mux gate cells */
+ for (n = 0; n < ARRAY_SIZE(asm9260_mux_gates); n++) {
+ const struct asm9260_gate_data *gd = &asm9260_mux_gates[n];
+
+ clk = clk_register_gate(NULL, gd->name,
+ gd->parent_name, gd->flags | CLK_SET_RATE_PARENT,
+ base + gd->reg, gd->bit_idx, 0, &asm9260_clk_lock);
+ }
+
+ /* clock div cells */
+ for (n = 0; n < ARRAY_SIZE(asm9260_div_clks); n++) {
+ const struct asm9260_div_clk *dc = &asm9260_div_clks[n];
+
+ clks[dc->idx] = clk_register_divider(NULL, dc->name,
+ dc->parent_name, CLK_SET_RATE_PARENT,
+ base + dc->reg, 0, 8, CLK_DIVIDER_ONE_BASED,
+ &asm9260_clk_lock);
+ }
+
+ /* clock ahb gate cells */
+ for (n = 0; n < ARRAY_SIZE(asm9260_ahb_gates); n++) {
+ const struct asm9260_gate_data *gd = &asm9260_ahb_gates[n];
+
+ clks[gd->idx] = clk_register_gate(NULL, gd->name,
+ gd->parent_name, gd->flags, base + gd->reg,
+ gd->bit_idx, 0, &asm9260_clk_lock);
+ }
+
+ /* check for errors on leaf clocks */
+ for (n = 0; n < MAX_CLKS; n++) {
+ if (!IS_ERR(clks[n]))
+ continue;
+
+ pr_err("%s: Unable to register leaf clock %d\n",
+ np->full_name, n);
+ goto fail;
+ }
+
+ /* register clk-provider */
+ clk_data.clks = clks;
+ clk_data.clk_num = MAX_CLKS;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ return;
+fail:
+ iounmap(base);
+}
+CLK_OF_DECLARE(asm9260_acc, "alphascale,asm9260-clock-controller",
+ asm9260_acc_init);
diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
new file mode 100644
index 00000000000000..c386ad25beb4af
--- /dev/null
+++ b/drivers/clk/clk-cdce706.c
@@ -0,0 +1,700 @@
+/*
+ * TI CDCE706 programmable 3-PLL clock synthesizer driver
+ *
+ * Copyright (c) 2014 Cadence Design Systems Inc.
+ *
+ * Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CDCE706_CLKIN_CLOCK 10
+#define CDCE706_CLKIN_SOURCE 11
+#define CDCE706_PLL_M_LOW(pll) (1 + 3 * (pll))
+#define CDCE706_PLL_N_LOW(pll) (2 + 3 * (pll))
+#define CDCE706_PLL_HI(pll) (3 + 3 * (pll))
+#define CDCE706_PLL_MUX 3
+#define CDCE706_PLL_FVCO 6
+#define CDCE706_DIVIDER(div) (13 + (div))
+#define CDCE706_CLKOUT(out) (19 + (out))
+
+#define CDCE706_CLKIN_CLOCK_MASK 0x10
+#define CDCE706_CLKIN_SOURCE_SHIFT 6
+#define CDCE706_CLKIN_SOURCE_MASK 0xc0
+#define CDCE706_CLKIN_SOURCE_LVCMOS 0x40
+
+#define CDCE706_PLL_MUX_MASK(pll) (0x80 >> (pll))
+#define CDCE706_PLL_LOW_M_MASK 0xff
+#define CDCE706_PLL_LOW_N_MASK 0xff
+#define CDCE706_PLL_HI_M_MASK 0x1
+#define CDCE706_PLL_HI_N_MASK 0x1e
+#define CDCE706_PLL_HI_N_SHIFT 1
+#define CDCE706_PLL_M_MAX 0x1ff
+#define CDCE706_PLL_N_MAX 0xfff
+#define CDCE706_PLL_FVCO_MASK(pll) (0x80 >> (pll))
+#define CDCE706_PLL_FREQ_MIN 80000000
+#define CDCE706_PLL_FREQ_MAX 300000000
+#define CDCE706_PLL_FREQ_HI 180000000
+
+#define CDCE706_DIVIDER_PLL(div) (9 + (div) - ((div) > 2) - ((div) > 4))
+#define CDCE706_DIVIDER_PLL_SHIFT(div) ((div) < 2 ? 5 : 3 * ((div) & 1))
+#define CDCE706_DIVIDER_PLL_MASK(div) (0x7 << CDCE706_DIVIDER_PLL_SHIFT(div))
+#define CDCE706_DIVIDER_DIVIDER_MASK 0x7f
+#define CDCE706_DIVIDER_DIVIDER_MAX 0x7f
+
+#define CDCE706_CLKOUT_DIVIDER_MASK 0x7
+#define CDCE706_CLKOUT_ENABLE_MASK 0x8
+
+static struct regmap_config cdce706_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+};
+
+#define to_hw_data(phw) (container_of((phw), struct cdce706_hw_data, hw))
+
+struct cdce706_hw_data {
+ struct cdce706_dev_data *dev_data;
+ unsigned idx;
+ unsigned parent;
+ struct clk *clk;
+ struct clk_hw hw;
+ unsigned div;
+ unsigned mul;
+ unsigned mux;
+};
+
+struct cdce706_dev_data {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct clk_onecell_data onecell;
+ struct clk *clks[6];
+ struct clk *clkin_clk[2];
+ const char *clkin_name[2];
+ struct cdce706_hw_data clkin[1];
+ struct cdce706_hw_data pll[3];
+ struct cdce706_hw_data divider[6];
+ struct cdce706_hw_data clkout[6];
+};
+
+static const char * const cdce706_source_name[] = {
+ "clk_in0", "clk_in1",
+};
+
+static const char *cdce706_clkin_name[] = {
+ "clk_in",
+};
+
+static const char * const cdce706_pll_name[] = {
+ "pll1", "pll2", "pll3",
+};
+
+static const char *cdce706_divider_parent_name[] = {
+ "clk_in", "pll1", "pll2", "pll2", "pll3",
+};
+
+static const char *cdce706_divider_name[] = {
+ "p0", "p1", "p2", "p3", "p4", "p5",
+};
+
+static const char * const cdce706_clkout_name[] = {
+ "clk_out0", "clk_out1", "clk_out2", "clk_out3", "clk_out4", "clk_out5",
+};
+
+static int cdce706_reg_read(struct cdce706_dev_data *dev_data, unsigned reg,
+ unsigned *val)
+{
+ int rc = regmap_read(dev_data->regmap, reg | 0x80, val);
+
+ if (rc < 0)
+ dev_err(&dev_data->client->dev, "error reading reg %u", reg);
+ return rc;
+}
+
+static int cdce706_reg_write(struct cdce706_dev_data *dev_data, unsigned reg,
+ unsigned val)
+{
+ int rc = regmap_write(dev_data->regmap, reg | 0x80, val);
+
+ if (rc < 0)
+ dev_err(&dev_data->client->dev, "error writing reg %u", reg);
+ return rc;
+}
+
+static int cdce706_reg_update(struct cdce706_dev_data *dev_data, unsigned reg,
+ unsigned mask, unsigned val)
+{
+ int rc = regmap_update_bits(dev_data->regmap, reg | 0x80, mask, val);
+
+ if (rc < 0)
+ dev_err(&dev_data->client->dev, "error updating reg %u", reg);
+ return rc;
+}
+
+static int cdce706_clkin_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ hwd->parent = index;
+ return 0;
+}
+
+static u8 cdce706_clkin_get_parent(struct clk_hw *hw)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ return hwd->parent;
+}
+
+static const struct clk_ops cdce706_clkin_ops = {
+ .set_parent = cdce706_clkin_set_parent,
+ .get_parent = cdce706_clkin_get_parent,
+};
+
+static unsigned long cdce706_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, pll: %d, mux: %d, mul: %u, div: %u\n",
+ __func__, hwd->idx, hwd->mux, hwd->mul, hwd->div);
+
+ if (!hwd->mux) {
+ if (hwd->div && hwd->mul) {
+ u64 res = (u64)parent_rate * hwd->mul;
+
+ do_div(res, hwd->div);
+ return res;
+ }
+ } else {
+ if (hwd->div)
+ return parent_rate / hwd->div;
+ }
+ return 0;
+}
+
+static long cdce706_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+ unsigned long mul, div;
+ u64 res;
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, rate: %lu, parent_rate: %lu\n",
+ __func__, rate, *parent_rate);
+
+ rational_best_approximation(rate, *parent_rate,
+ CDCE706_PLL_N_MAX, CDCE706_PLL_M_MAX,
+ &mul, &div);
+ hwd->mul = mul;
+ hwd->div = div;
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, pll: %d, mul: %lu, div: %lu\n",
+ __func__, hwd->idx, mul, div);
+
+ res = (u64)*parent_rate * hwd->mul;
+ do_div(res, hwd->div);
+ return res;
+}
+
+static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+ unsigned long mul = hwd->mul, div = hwd->div;
+ int err;
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, pll: %d, mul: %lu, div: %lu\n",
+ __func__, hwd->idx, mul, div);
+
+ err = cdce706_reg_update(hwd->dev_data,
+ CDCE706_PLL_HI(hwd->idx),
+ CDCE706_PLL_HI_M_MASK | CDCE706_PLL_HI_N_MASK,
+ ((div >> 8) & CDCE706_PLL_HI_M_MASK) |
+ ((mul >> (8 - CDCE706_PLL_HI_N_SHIFT)) &
+ CDCE706_PLL_HI_N_MASK));
+ if (err < 0)
+ return err;
+
+ err = cdce706_reg_write(hwd->dev_data,
+ CDCE706_PLL_M_LOW(hwd->idx),
+ div & CDCE706_PLL_LOW_M_MASK);
+ if (err < 0)
+ return err;
+
+ err = cdce706_reg_write(hwd->dev_data,
+ CDCE706_PLL_N_LOW(hwd->idx),
+ mul & CDCE706_PLL_LOW_N_MASK);
+ if (err < 0)
+ return err;
+
+ err = cdce706_reg_update(hwd->dev_data,
+ CDCE706_PLL_FVCO,
+ CDCE706_PLL_FVCO_MASK(hwd->idx),
+ rate > CDCE706_PLL_FREQ_HI ?
+ CDCE706_PLL_FVCO_MASK(hwd->idx) : 0);
+ return err;
+}
+
+static const struct clk_ops cdce706_pll_ops = {
+ .recalc_rate = cdce706_pll_recalc_rate,
+ .round_rate = cdce706_pll_round_rate,
+ .set_rate = cdce706_pll_set_rate,
+};
+
+static int cdce706_divider_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ if (hwd->parent == index)
+ return 0;
+ hwd->parent = index;
+ return cdce706_reg_update(hwd->dev_data,
+ CDCE706_DIVIDER_PLL(hwd->idx),
+ CDCE706_DIVIDER_PLL_MASK(hwd->idx),
+ index << CDCE706_DIVIDER_PLL_SHIFT(hwd->idx));
+}
+
+static u8 cdce706_divider_get_parent(struct clk_hw *hw)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ return hwd->parent;
+}
+
+static unsigned long cdce706_divider_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, divider: %d, div: %u\n",
+ __func__, hwd->idx, hwd->div);
+ if (hwd->div)
+ return parent_rate / hwd->div;
+ return 0;
+}
+
+static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+ struct cdce706_dev_data *cdce = hwd->dev_data;
+ unsigned long mul, div;
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, rate: %lu, parent_rate: %lu\n",
+ __func__, rate, *parent_rate);
+
+ rational_best_approximation(rate, *parent_rate,
+ 1, CDCE706_DIVIDER_DIVIDER_MAX,
+ &mul, &div);
+ if (!mul)
+ div = CDCE706_DIVIDER_DIVIDER_MAX;
+
+ if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+ unsigned long best_diff = rate;
+ unsigned long best_div = 0;
+ struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
+ unsigned long gp_rate = gp_clk ? clk_get_rate(gp_clk) : 0;
+
+ for (div = CDCE706_PLL_FREQ_MIN / rate; best_diff &&
+ div <= CDCE706_PLL_FREQ_MAX / rate; ++div) {
+ unsigned long n, m;
+ unsigned long diff;
+ unsigned long div_rate;
+ u64 div_rate64;
+
+ if (rate * div < CDCE706_PLL_FREQ_MIN)
+ continue;
+
+ rational_best_approximation(rate * div, gp_rate,
+ CDCE706_PLL_N_MAX,
+ CDCE706_PLL_M_MAX,
+ &n, &m);
+ div_rate64 = (u64)gp_rate * n;
+ do_div(div_rate64, m);
+ do_div(div_rate64, div);
+ div_rate = div_rate64;
+ diff = max(div_rate, rate) - min(div_rate, rate);
+
+ if (diff < best_diff) {
+ best_diff = diff;
+ best_div = div;
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, %lu * %lu / %lu / %lu = %lu\n",
+ __func__, gp_rate, n, m, div, div_rate);
+ }
+ }
+
+ div = best_div;
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, altering parent rate: %lu -> %lu\n",
+ __func__, *parent_rate, rate * div);
+ *parent_rate = rate * div;
+ }
+ hwd->div = div;
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, divider: %d, div: %lu\n",
+ __func__, hwd->idx, div);
+
+ return *parent_rate / div;
+}
+
+static int cdce706_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ dev_dbg(&hwd->dev_data->client->dev,
+ "%s, divider: %d, div: %u\n",
+ __func__, hwd->idx, hwd->div);
+
+ return cdce706_reg_update(hwd->dev_data,
+ CDCE706_DIVIDER(hwd->idx),
+ CDCE706_DIVIDER_DIVIDER_MASK,
+ hwd->div);
+}
+
+static const struct clk_ops cdce706_divider_ops = {
+ .set_parent = cdce706_divider_set_parent,
+ .get_parent = cdce706_divider_get_parent,
+ .recalc_rate = cdce706_divider_recalc_rate,
+ .round_rate = cdce706_divider_round_rate,
+ .set_rate = cdce706_divider_set_rate,
+};
+
+static int cdce706_clkout_prepare(struct clk_hw *hw)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ return cdce706_reg_update(hwd->dev_data, CDCE706_CLKOUT(hwd->idx),
+ CDCE706_CLKOUT_ENABLE_MASK,
+ CDCE706_CLKOUT_ENABLE_MASK);
+}
+
+static void cdce706_clkout_unprepare(struct clk_hw *hw)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ cdce706_reg_update(hwd->dev_data, CDCE706_CLKOUT(hwd->idx),
+ CDCE706_CLKOUT_ENABLE_MASK, 0);
+}
+
+static int cdce706_clkout_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ if (hwd->parent == index)
+ return 0;
+ hwd->parent = index;
+ return cdce706_reg_update(hwd->dev_data,
+ CDCE706_CLKOUT(hwd->idx),
+ CDCE706_CLKOUT_ENABLE_MASK, index);
+}
+
+static u8 cdce706_clkout_get_parent(struct clk_hw *hw)
+{
+ struct cdce706_hw_data *hwd = to_hw_data(hw);
+
+ return hwd->parent;
+}
+
+static unsigned long cdce706_clkout_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate;
+}
+
+static long cdce706_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ *parent_rate = rate;
+ return rate;
+}
+
+static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return 0;
+}
+
+static const struct clk_ops cdce706_clkout_ops = {
+ .prepare = cdce706_clkout_prepare,
+ .unprepare = cdce706_clkout_unprepare,
+ .set_parent = cdce706_clkout_set_parent,
+ .get_parent = cdce706_clkout_get_parent,
+ .recalc_rate = cdce706_clkout_recalc_rate,
+ .round_rate = cdce706_clkout_round_rate,
+ .set_rate = cdce706_clkout_set_rate,
+};
+
+static int cdce706_register_hw(struct cdce706_dev_data *cdce,
+ struct cdce706_hw_data *hw, unsigned num_hw,
+ const char * const *clk_names,
+ struct clk_init_data *init)
+{
+ unsigned i;
+
+ for (i = 0; i < num_hw; ++i, ++hw) {
+ init->name = clk_names[i];
+ hw->dev_data = cdce;
+ hw->idx = i;
+ hw->hw.init = init;
+ hw->clk = devm_clk_register(&cdce->client->dev,
+ &hw->hw);
+ if (IS_ERR(hw->clk)) {
+ dev_err(&cdce->client->dev, "Failed to register %s\n",
+ clk_names[i]);
+ return PTR_ERR(hw->clk);
+ }
+ }
+ return 0;
+}
+
+static int cdce706_register_clkin(struct cdce706_dev_data *cdce)
+{
+ struct clk_init_data init = {
+ .ops = &cdce706_clkin_ops,
+ .parent_names = cdce->clkin_name,
+ .num_parents = ARRAY_SIZE(cdce->clkin_name),
+ };
+ unsigned i;
+ int ret;
+ unsigned clock, source;
+
+ for (i = 0; i < ARRAY_SIZE(cdce->clkin_name); ++i) {
+ struct clk *parent = devm_clk_get(&cdce->client->dev,
+ cdce706_source_name[i]);
+
+ if (IS_ERR(parent)) {
+ cdce->clkin_name[i] = cdce706_source_name[i];
+ } else {
+ cdce->clkin_name[i] = __clk_get_name(parent);
+ cdce->clkin_clk[i] = parent;
+ }
+ }
+
+ ret = cdce706_reg_read(cdce, CDCE706_CLKIN_SOURCE, &source);
+ if (ret < 0)
+ return ret;
+ if ((source & CDCE706_CLKIN_SOURCE_MASK) ==
+ CDCE706_CLKIN_SOURCE_LVCMOS) {
+ ret = cdce706_reg_read(cdce, CDCE706_CLKIN_CLOCK, &clock);
+ if (ret < 0)
+ return ret;
+ cdce->clkin[0].parent = !!(clock & CDCE706_CLKIN_CLOCK_MASK);
+ }
+
+ ret = cdce706_register_hw(cdce, cdce->clkin,
+ ARRAY_SIZE(cdce->clkin),
+ cdce706_clkin_name, &init);
+ return ret;
+}
+
+static int cdce706_register_plls(struct cdce706_dev_data *cdce)
+{
+ struct clk_init_data init = {
+ .ops = &cdce706_pll_ops,
+ .parent_names = cdce706_clkin_name,
+ .num_parents = ARRAY_SIZE(cdce706_clkin_name),
+ };
+ unsigned i;
+ int ret;
+ unsigned mux;
+
+ ret = cdce706_reg_read(cdce, CDCE706_PLL_MUX, &mux);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(cdce->pll); ++i) {
+ unsigned m, n, v;
+
+ ret = cdce706_reg_read(cdce, CDCE706_PLL_M_LOW(i), &m);
+ if (ret < 0)
+ return ret;
+ ret = cdce706_reg_read(cdce, CDCE706_PLL_N_LOW(i), &n);
+ if (ret < 0)
+ return ret;
+ ret = cdce706_reg_read(cdce, CDCE706_PLL_HI(i), &v);
+ if (ret < 0)
+ return ret;
+ cdce->pll[i].div = m | ((v & CDCE706_PLL_HI_M_MASK) << 8);
+ cdce->pll[i].mul = n | ((v & CDCE706_PLL_HI_N_MASK) <<
+ (8 - CDCE706_PLL_HI_N_SHIFT));
+ cdce->pll[i].mux = mux & CDCE706_PLL_MUX_MASK(i);
+ dev_dbg(&cdce->client->dev,
+ "%s: i: %u, div: %u, mul: %u, mux: %d\n", __func__, i,
+ cdce->pll[i].div, cdce->pll[i].mul, cdce->pll[i].mux);
+ }
+
+ ret = cdce706_register_hw(cdce, cdce->pll,
+ ARRAY_SIZE(cdce->pll),
+ cdce706_pll_name, &init);
+ return ret;
+}
+
+static int cdce706_register_dividers(struct cdce706_dev_data *cdce)
+{
+ struct clk_init_data init = {
+ .ops = &cdce706_divider_ops,
+ .parent_names = cdce706_divider_parent_name,
+ .num_parents = ARRAY_SIZE(cdce706_divider_parent_name),
+ .flags = CLK_SET_RATE_PARENT,
+ };
+ unsigned i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(cdce->divider); ++i) {
+ unsigned val;
+
+ ret = cdce706_reg_read(cdce, CDCE706_DIVIDER_PLL(i), &val);
+ if (ret < 0)
+ return ret;
+ cdce->divider[i].parent =
+ (val & CDCE706_DIVIDER_PLL_MASK(i)) >>
+ CDCE706_DIVIDER_PLL_SHIFT(i);
+
+ ret = cdce706_reg_read(cdce, CDCE706_DIVIDER(i), &val);
+ if (ret < 0)
+ return ret;
+ cdce->divider[i].div = val & CDCE706_DIVIDER_DIVIDER_MASK;
+ dev_dbg(&cdce->client->dev,
+ "%s: i: %u, parent: %u, div: %u\n", __func__, i,
+ cdce->divider[i].parent, cdce->divider[i].div);
+ }
+
+ ret = cdce706_register_hw(cdce, cdce->divider,
+ ARRAY_SIZE(cdce->divider),
+ cdce706_divider_name, &init);
+ return ret;
+}
+
+static int cdce706_register_clkouts(struct cdce706_dev_data *cdce)
+{
+ struct clk_init_data init = {
+ .ops = &cdce706_clkout_ops,
+ .parent_names = cdce706_divider_name,
+ .num_parents = ARRAY_SIZE(cdce706_divider_name),
+ .flags = CLK_SET_RATE_PARENT,
+ };
+ unsigned i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(cdce->clkout); ++i) {
+ unsigned val;
+
+ ret = cdce706_reg_read(cdce, CDCE706_CLKOUT(i), &val);
+ if (ret < 0)
+ return ret;
+ cdce->clkout[i].parent = val & CDCE706_CLKOUT_DIVIDER_MASK;
+ dev_dbg(&cdce->client->dev,
+ "%s: i: %u, parent: %u\n", __func__, i,
+ cdce->clkout[i].parent);
+ }
+
+ ret = cdce706_register_hw(cdce, cdce->clkout,
+ ARRAY_SIZE(cdce->clkout),
+ cdce706_clkout_name, &init);
+ for (i = 0; i < ARRAY_SIZE(cdce->clkout); ++i)
+ cdce->clks[i] = cdce->clkout[i].clk;
+
+ return ret;
+}
+
+static int cdce706_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct cdce706_dev_data *cdce;
+ int ret;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ cdce = devm_kzalloc(&client->dev, sizeof(*cdce), GFP_KERNEL);
+ if (!cdce)
+ return -ENOMEM;
+
+ cdce->client = client;
+ cdce->regmap = devm_regmap_init_i2c(client, &cdce706_regmap_config);
+ if (IS_ERR(cdce->regmap)) {
+ dev_err(&client->dev, "Failed to initialize regmap\n");
+ return -EINVAL;
+ }
+
+ i2c_set_clientdata(client, cdce);
+
+ ret = cdce706_register_clkin(cdce);
+ if (ret < 0)
+ return ret;
+ ret = cdce706_register_plls(cdce);
+ if (ret < 0)
+ return ret;
+ ret = cdce706_register_dividers(cdce);
+ if (ret < 0)
+ return ret;
+ ret = cdce706_register_clkouts(cdce);
+ if (ret < 0)
+ return ret;
+ cdce->onecell.clks = cdce->clks;
+ cdce->onecell.clk_num = ARRAY_SIZE(cdce->clks);
+ ret = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
+ &cdce->onecell);
+
+ return ret;
+}
+
+static int cdce706_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+
+#ifdef CONFIG_OF
+static const struct of_device_id cdce706_dt_match[] = {
+ { .compatible = "ti,cdce706" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, cdce706_dt_match);
+#endif
+
+static const struct i2c_device_id cdce706_id[] = {
+ { "cdce706", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cdce706_id);
+
+static struct i2c_driver cdce706_i2c_driver = {
+ .driver = {
+ .name = "cdce706",
+ .of_match_table = of_match_ptr(cdce706_dt_match),
+ },
+ .probe = cdce706_probe,
+ .remove = cdce706_remove,
+ .id_table = cdce706_id,
+};
+module_i2c_driver(cdce706_i2c_driver);
+
+MODULE_AUTHOR("Max Filippov ");
+MODULE_DESCRIPTION("TI CDCE 706 clock synthesizer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 4386697236a78d..956b7e54fa1c5f 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -27,7 +27,7 @@ static u8 clk_composite_get_parent(struct clk_hw *hw)
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *mux_hw = composite->mux_hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return mux_ops->get_parent(mux_hw);
}
@@ -38,7 +38,7 @@ static int clk_composite_set_parent(struct clk_hw *hw, u8 index)
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *mux_hw = composite->mux_hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return mux_ops->set_parent(mux_hw, index);
}
@@ -50,12 +50,14 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk_hw *rate_hw = composite->rate_hw;
- rate_hw->clk = hw->clk;
+ __clk_hw_set_clk(rate_hw, hw);
return rate_ops->recalc_rate(rate_hw, parent_rate);
}
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p)
{
@@ -72,8 +74,10 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
int i;
if (rate_hw && rate_ops && rate_ops->determine_rate) {
- rate_hw->clk = hw->clk;
- return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
+ __clk_hw_set_clk(rate_hw, hw);
+ return rate_ops->determine_rate(rate_hw, rate, min_rate,
+ max_rate,
+ best_parent_rate,
best_parent_p);
} else if (rate_hw && rate_ops && rate_ops->round_rate &&
mux_hw && mux_ops && mux_ops->set_parent) {
@@ -116,8 +120,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
return best_rate;
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
- mux_hw->clk = hw->clk;
- return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
+ __clk_hw_set_clk(mux_hw, hw);
+ return mux_ops->determine_rate(mux_hw, rate, min_rate,
+ max_rate, best_parent_rate,
best_parent_p);
} else {
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
@@ -132,7 +137,7 @@ static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk_hw *rate_hw = composite->rate_hw;
- rate_hw->clk = hw->clk;
+ __clk_hw_set_clk(rate_hw, hw);
return rate_ops->round_rate(rate_hw, rate, prate);
}
@@ -144,7 +149,7 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk_hw *rate_hw = composite->rate_hw;
- rate_hw->clk = hw->clk;
+ __clk_hw_set_clk(rate_hw, hw);
return rate_ops->set_rate(rate_hw, rate, parent_rate);
}
@@ -155,7 +160,7 @@ static int clk_composite_is_enabled(struct clk_hw *hw)
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk_hw *gate_hw = composite->gate_hw;
- gate_hw->clk = hw->clk;
+ __clk_hw_set_clk(gate_hw, hw);
return gate_ops->is_enabled(gate_hw);
}
@@ -166,7 +171,7 @@ static int clk_composite_enable(struct clk_hw *hw)
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk_hw *gate_hw = composite->gate_hw;
- gate_hw->clk = hw->clk;
+ __clk_hw_set_clk(gate_hw, hw);
return gate_ops->enable(gate_hw);
}
@@ -177,7 +182,7 @@ static void clk_composite_disable(struct clk_hw *hw)
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk_hw *gate_hw = composite->gate_hw;
- gate_hw->clk = hw->clk;
+ __clk_hw_set_clk(gate_hw, hw);
gate_ops->disable(gate_hw);
}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index c0a842b335c520..db7f8bce7467a2 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -30,7 +30,7 @@
#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
-#define div_mask(d) ((1 << ((d)->width)) - 1)
+#define div_mask(width) ((1 << (width)) - 1)
static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
{
@@ -54,15 +54,16 @@ static unsigned int _get_table_mindiv(const struct clk_div_table *table)
return mindiv;
}
-static unsigned int _get_maxdiv(struct clk_divider *divider)
+static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
+ unsigned long flags)
{
- if (divider->flags & CLK_DIVIDER_ONE_BASED)
- return div_mask(divider);
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
- return 1 << div_mask(divider);
- if (divider->table)
- return _get_table_maxdiv(divider->table);
- return div_mask(divider) + 1;
+ if (flags & CLK_DIVIDER_ONE_BASED)
+ return div_mask(width);
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
+ return 1 << div_mask(width);
+ if (table)
+ return _get_table_maxdiv(table);
+ return div_mask(width) + 1;
}
static unsigned int _get_table_div(const struct clk_div_table *table,
@@ -76,14 +77,15 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
return 0;
}
-static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+static unsigned int _get_div(const struct clk_div_table *table,
+ unsigned int val, unsigned long flags)
{
- if (divider->flags & CLK_DIVIDER_ONE_BASED)
+ if (flags & CLK_DIVIDER_ONE_BASED)
return val;
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << val;
- if (divider->table)
- return _get_table_div(divider->table, val);
+ if (table)
+ return _get_table_div(table, val);
return val + 1;
}
@@ -98,29 +100,28 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
return 0;
}
-static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
+static unsigned int _get_val(const struct clk_div_table *table,
+ unsigned int div, unsigned long flags)
{
- if (divider->flags & CLK_DIVIDER_ONE_BASED)
+ if (flags & CLK_DIVIDER_ONE_BASED)
return div;
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
return __ffs(div);
- if (divider->table)
- return _get_table_val(divider->table, div);
+ if (table)
+ return _get_table_val(table, div);
return div - 1;
}
-static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
+ unsigned int val,
+ const struct clk_div_table *table,
+ unsigned long flags)
{
- struct clk_divider *divider = to_clk_divider(hw);
- unsigned int div, val;
+ unsigned int div;
- val = clk_readl(divider->reg) >> divider->shift;
- val &= div_mask(divider);
-
- div = _get_div(divider, val);
+ div = _get_div(table, val, flags);
if (!div) {
- WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
+ WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
__clk_get_name(hw->clk));
return parent_rate;
@@ -128,6 +129,20 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
return DIV_ROUND_UP(parent_rate, div);
}
+EXPORT_SYMBOL_GPL(divider_recalc_rate);
+
+static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned int val;
+
+ val = clk_readl(divider->reg) >> divider->shift;
+ val &= div_mask(divider->width);
+
+ return divider_recalc_rate(hw, parent_rate, val, divider->table,
+ divider->flags);
+}
/*
* The reverse of DIV_ROUND_UP: The maximum number which
@@ -146,12 +161,13 @@ static bool _is_valid_table_div(const struct clk_div_table *table,
return false;
}
-static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
+static bool _is_valid_div(const struct clk_div_table *table, unsigned int div,
+ unsigned long flags)
{
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
return is_power_of_2(div);
- if (divider->table)
- return _is_valid_table_div(divider->table, div);
+ if (table)
+ return _is_valid_table_div(table, div);
return true;
}
@@ -191,71 +207,76 @@ static int _round_down_table(const struct clk_div_table *table, int div)
return down;
}
-static int _div_round_up(struct clk_divider *divider,
- unsigned long parent_rate, unsigned long rate)
+static int _div_round_up(const struct clk_div_table *table,
+ unsigned long parent_rate, unsigned long rate,
+ unsigned long flags)
{
int div = DIV_ROUND_UP(parent_rate, rate);
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
div = __roundup_pow_of_two(div);
- if (divider->table)
- div = _round_up_table(divider->table, div);
+ if (table)
+ div = _round_up_table(table, div);
return div;
}
-static int _div_round_closest(struct clk_divider *divider,
- unsigned long parent_rate, unsigned long rate)
+static int _div_round_closest(const struct clk_div_table *table,
+ unsigned long parent_rate, unsigned long rate,
+ unsigned long flags)
{
int up, down, div;
up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate);
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) {
+ if (flags & CLK_DIVIDER_POWER_OF_TWO) {
up = __roundup_pow_of_two(div);
down = __rounddown_pow_of_two(div);
- } else if (divider->table) {
- up = _round_up_table(divider->table, div);
- down = _round_down_table(divider->table, div);
+ } else if (table) {
+ up = _round_up_table(table, div);
+ down = _round_down_table(table, div);
}
return (up - div) <= (div - down) ? up : down;
}
-static int _div_round(struct clk_divider *divider, unsigned long parent_rate,
- unsigned long rate)
+static int _div_round(const struct clk_div_table *table,
+ unsigned long parent_rate, unsigned long rate,
+ unsigned long flags)
{
- if (divider->flags & CLK_DIVIDER_ROUND_CLOSEST)
- return _div_round_closest(divider, parent_rate, rate);
+ if (flags & CLK_DIVIDER_ROUND_CLOSEST)
+ return _div_round_closest(table, parent_rate, rate, flags);
- return _div_round_up(divider, parent_rate, rate);
+ return _div_round_up(table, parent_rate, rate, flags);
}
-static bool _is_best_div(struct clk_divider *divider,
- unsigned long rate, unsigned long now, unsigned long best)
+static bool _is_best_div(unsigned long rate, unsigned long now,
+ unsigned long best, unsigned long flags)
{
- if (divider->flags & CLK_DIVIDER_ROUND_CLOSEST)
+ if (flags & CLK_DIVIDER_ROUND_CLOSEST)
return abs(rate - now) < abs(rate - best);
return now <= rate && now > best;
}
-static int _next_div(struct clk_divider *divider, int div)
+static int _next_div(const struct clk_div_table *table, int div,
+ unsigned long flags)
{
div++;
- if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
return __roundup_pow_of_two(div);
- if (divider->table)
- return _round_up_table(divider->table, div);
+ if (table)
+ return _round_up_table(table, div);
return div;
}
static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
- unsigned long *best_parent_rate)
+ unsigned long *best_parent_rate,
+ const struct clk_div_table *table, u8 width,
+ unsigned long flags)
{
- struct clk_divider *divider = to_clk_divider(hw);
int i, bestdiv = 0;
unsigned long parent_rate, best = 0, now, maxdiv;
unsigned long parent_rate_saved = *best_parent_rate;
@@ -263,19 +284,11 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
if (!rate)
rate = 1;
- /* if read only, just return current value */
- if (divider->flags & CLK_DIVIDER_READ_ONLY) {
- bestdiv = readl(divider->reg) >> divider->shift;
- bestdiv &= div_mask(divider);
- bestdiv = _get_div(divider, bestdiv);
- return bestdiv;
- }
-
- maxdiv = _get_maxdiv(divider);
+ maxdiv = _get_maxdiv(table, width, flags);
if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
parent_rate = *best_parent_rate;
- bestdiv = _div_round(divider, parent_rate, rate);
+ bestdiv = _div_round(table, parent_rate, rate, flags);
bestdiv = bestdiv == 0 ? 1 : bestdiv;
bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
return bestdiv;
@@ -287,8 +300,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
*/
maxdiv = min(ULONG_MAX / rate, maxdiv);
- for (i = 1; i <= maxdiv; i = _next_div(divider, i)) {
- if (!_is_valid_div(divider, i))
+ for (i = 1; i <= maxdiv; i = _next_div(table, i, flags)) {
+ if (!_is_valid_div(table, i, flags))
continue;
if (rate * i == parent_rate_saved) {
/*
@@ -302,7 +315,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
MULT_ROUND_UP(rate, i));
now = DIV_ROUND_UP(parent_rate, i);
- if (_is_best_div(divider, rate, now, best)) {
+ if (_is_best_div(rate, now, best, flags)) {
bestdiv = i;
best = now;
*best_parent_rate = parent_rate;
@@ -310,48 +323,79 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
}
if (!bestdiv) {
- bestdiv = _get_maxdiv(divider);
+ bestdiv = _get_maxdiv(table, width, flags);
*best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
}
return bestdiv;
}
-static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+long divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate, const struct clk_div_table *table,
+ u8 width, unsigned long flags)
{
int div;
- div = clk_divider_bestdiv(hw, rate, prate);
+
+ div = clk_divider_bestdiv(hw, rate, prate, table, width, flags);
return DIV_ROUND_UP(*prate, div);
}
+EXPORT_SYMBOL_GPL(divider_round_rate);
-static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
+static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
{
struct clk_divider *divider = to_clk_divider(hw);
+ int bestdiv;
+
+ /* if read only, just return current value */
+ if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+ bestdiv = readl(divider->reg) >> divider->shift;
+ bestdiv &= div_mask(divider->width);
+ bestdiv = _get_div(divider->table, bestdiv, divider->flags);
+ return bestdiv;
+ }
+
+ return divider_round_rate(hw, rate, prate, divider->table,
+ divider->width, divider->flags);
+}
+
+int divider_get_val(unsigned long rate, unsigned long parent_rate,
+ const struct clk_div_table *table, u8 width,
+ unsigned long flags)
+{
unsigned int div, value;
- unsigned long flags = 0;
- u32 val;
div = DIV_ROUND_UP(parent_rate, rate);
- if (!_is_valid_div(divider, div))
+ if (!_is_valid_div(table, div, flags))
return -EINVAL;
- value = _get_val(divider, div);
+ value = _get_val(table, div, flags);
+
+ return min_t(unsigned int, value, div_mask(width));
+}
+EXPORT_SYMBOL_GPL(divider_get_val);
+
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned int value;
+ unsigned long flags = 0;
+ u32 val;
- if (value > div_mask(divider))
- value = div_mask(divider);
+ value = divider_get_val(rate, parent_rate, divider->table,
+ divider->width, divider->flags);
if (divider->lock)
spin_lock_irqsave(divider->lock, flags);
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
- val = div_mask(divider) << (divider->shift + 16);
+ val = div_mask(divider->width) << (divider->shift + 16);
} else {
val = clk_readl(divider->reg);
- val &= ~(div_mask(divider) << divider->shift);
+ val &= ~(div_mask(divider->width) << divider->shift);
}
val |= value << divider->shift;
clk_writel(val, divider->reg);
@@ -463,3 +507,19 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
width, clk_divider_flags, table, lock);
}
EXPORT_SYMBOL_GPL(clk_register_divider_table);
+
+void clk_unregister_divider(struct clk *clk)
+{
+ struct clk_divider *div;
+ struct clk_hw *hw;
+
+ hw = __clk_get_hw(clk);
+ if (!hw)
+ return;
+
+ div = to_clk_divider(hw);
+
+ clk_unregister(clk);
+ kfree(div);
+}
+EXPORT_SYMBOL_GPL(clk_unregister_divider);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 51fd87fb7ba691..3f0e4200cb5d4c 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -128,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
struct clk_init_data init;
if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
- if (bit_idx > 16) {
+ if (bit_idx > 15) {
pr_err("gate bit exceeds LOWORD field\n");
return ERR_PTR(-EINVAL);
}
@@ -162,3 +162,19 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
return clk;
}
EXPORT_SYMBOL_GPL(clk_register_gate);
+
+void clk_unregister_gate(struct clk *clk)
+{
+ struct clk_gate *gate;
+ struct clk_hw *hw;
+
+ hw = __clk_get_hw(clk);
+ if (!hw)
+ return;
+
+ gate = to_clk_gate(hw);
+
+ clk_unregister(clk);
+ kfree(gate);
+}
+EXPORT_SYMBOL_GPL(clk_unregister_gate);
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 6e1ecf94bf58da..69a094c3783d8e 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -177,3 +177,19 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
NULL, lock);
}
EXPORT_SYMBOL_GPL(clk_register_mux);
+
+void clk_unregister_mux(struct clk *clk)
+{
+ struct clk_mux *mux;
+ struct clk_hw *hw;
+
+ hw = __clk_get_hw(clk);
+ if (!hw)
+ return;
+
+ mux = to_clk_mux(hw);
+
+ clk_unregister(clk);
+ kfree(mux);
+}
+EXPORT_SYMBOL_GPL(clk_unregister_mux);
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-qoriq.c
similarity index 59%
rename from drivers/clk/clk-ppc-corenet.c
rename to drivers/clk/clk-qoriq.c
index 0a47d6f49cd6f3..cda90a971e39b9 100644
--- a/drivers/clk/clk-ppc-corenet.c
+++ b/drivers/clk/clk-qoriq.c
@@ -5,8 +5,11 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * clock driver for Freescale PowerPC corenet SoCs.
+ * clock driver for Freescale QorIQ SoCs.
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include
#include
#include
@@ -19,6 +22,7 @@
struct cmux_clk {
struct clk_hw hw;
void __iomem *reg;
+ unsigned int clk_per_pll;
u32 flags;
};
@@ -27,14 +31,12 @@ struct cmux_clk {
#define CLKSEL_ADJUST BIT(0)
#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw)
-static unsigned int clocks_per_pll;
-
static int cmux_set_parent(struct clk_hw *hw, u8 idx)
{
struct cmux_clk *clk = to_cmux_clk(hw);
u32 clksel;
- clksel = ((idx / clocks_per_pll) << 2) + idx % clocks_per_pll;
+ clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll;
if (clk->flags & CLKSEL_ADJUST)
clksel += 8;
clksel = (clksel & 0xf) << CLKSEL_SHIFT;
@@ -52,12 +54,12 @@ static u8 cmux_get_parent(struct clk_hw *hw)
clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
if (clk->flags & CLKSEL_ADJUST)
clksel -= 8;
- clksel = (clksel >> 2) * clocks_per_pll + clksel % 4;
+ clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4;
return clksel;
}
-const struct clk_ops cmux_ops = {
+static const struct clk_ops cmux_ops = {
.get_parent = cmux_get_parent,
.set_parent = cmux_set_parent,
};
@@ -72,6 +74,7 @@ static void __init core_mux_init(struct device_node *np)
u32 offset;
const char *clk_name;
const char **parent_names;
+ struct of_phandle_args clkspec;
rc = of_property_read_u32(np, "reg", &offset);
if (rc) {
@@ -85,32 +88,40 @@ static void __init core_mux_init(struct device_node *np)
pr_err("%s: get clock count error\n", np->name);
return;
}
- parent_names = kzalloc((sizeof(char *) * count), GFP_KERNEL);
- if (!parent_names) {
- pr_err("%s: could not allocate parent_names\n", __func__);
+ parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
+ if (!parent_names)
return;
- }
for (i = 0; i < count; i++)
parent_names[i] = of_clk_get_parent_name(np, i);
- cmux_clk = kzalloc(sizeof(struct cmux_clk), GFP_KERNEL);
- if (!cmux_clk) {
- pr_err("%s: could not allocate cmux_clk\n", __func__);
+ cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL);
+ if (!cmux_clk)
goto err_name;
- }
+
cmux_clk->reg = of_iomap(np, 0);
if (!cmux_clk->reg) {
pr_err("%s: could not map register\n", __func__);
goto err_clk;
}
+ rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
+ &clkspec);
+ if (rc) {
+ pr_err("%s: parse clock node error\n", __func__);
+ goto err_clk;
+ }
+
+ cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np,
+ "clock-output-names");
+ of_node_put(clkspec.np);
+
node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
if (node && (offset >= 0x80))
cmux_clk->flags = CLKSEL_ADJUST;
rc = of_property_read_string_index(np, "clock-output-names",
- 0, &clk_name);
+ 0, &clk_name);
if (rc) {
pr_err("%s: read clock names error\n", np->name);
goto err_clk;
@@ -132,7 +143,7 @@ static void __init core_mux_init(struct device_node *np)
rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
if (rc) {
pr_err("Could not register clock provider for node:%s\n",
- np->name);
+ np->name);
goto err_clk;
}
goto err_name;
@@ -155,7 +166,7 @@ static void __init core_pll_init(struct device_node *np)
base = of_iomap(np, 0);
if (!base) {
- pr_err("clk-ppc: iomap error\n");
+ pr_err("iomap error\n");
return;
}
@@ -181,24 +192,17 @@ static void __init core_pll_init(struct device_node *np)
goto err_map;
}
- /* output clock number per PLL */
- clocks_per_pll = count;
-
- subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL);
- if (!subclks) {
- pr_err("%s: could not allocate subclks\n", __func__);
+ subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
+ if (!subclks)
goto err_map;
- }
- onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
- if (!onecell_data) {
- pr_err("%s: could not allocate onecell_data\n", __func__);
+ onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
+ if (!onecell_data)
goto err_clks;
- }
for (i = 0; i < count; i++) {
rc = of_property_read_string_index(np, "clock-output-names",
- i, &clk_name);
+ i, &clk_name);
if (rc) {
pr_err("%s: could not get clock names\n", np->name);
goto err_cell;
@@ -230,7 +234,7 @@ static void __init core_pll_init(struct device_node *np)
rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
if (rc) {
pr_err("Could not register clk provider for node:%s\n",
- np->name);
+ np->name);
goto err_cell;
}
@@ -252,7 +256,7 @@ static void __init sysclk_init(struct device_node *node)
u32 rate;
if (!np) {
- pr_err("ppc-clk: could not get parent node\n");
+ pr_err("could not get parent node\n");
return;
}
@@ -268,39 +272,91 @@ static void __init sysclk_init(struct device_node *node)
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
-static const struct of_device_id clk_match[] __initconst = {
- { .compatible = "fsl,qoriq-sysclk-1.0", .data = sysclk_init, },
- { .compatible = "fsl,qoriq-sysclk-2.0", .data = sysclk_init, },
- { .compatible = "fsl,qoriq-core-pll-1.0", .data = core_pll_init, },
- { .compatible = "fsl,qoriq-core-pll-2.0", .data = core_pll_init, },
- { .compatible = "fsl,qoriq-core-mux-1.0", .data = core_mux_init, },
- { .compatible = "fsl,qoriq-core-mux-2.0", .data = core_mux_init, },
- {}
-};
-
-static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
+static void __init pltfrm_pll_init(struct device_node *np)
{
- of_clk_init(clk_match);
+ void __iomem *base;
+ uint32_t mult;
+ const char *parent_name, *clk_name;
+ int i, _errno;
+ struct clk_onecell_data *cod;
- return 0;
-}
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
+ return;
+ }
-static const struct of_device_id ppc_clk_ids[] __initconst = {
- { .compatible = "fsl,qoriq-clockgen-1.0", },
- { .compatible = "fsl,qoriq-clockgen-2.0", },
- {}
-};
+ /* Get the multiple of PLL */
+ mult = ioread32be(base);
-static struct platform_driver ppc_corenet_clk_driver = {
- .driver = {
- .name = "ppc_corenet_clock",
- .of_match_table = ppc_clk_ids,
- },
- .probe = ppc_corenet_clk_probe,
-};
+ iounmap(base);
-static int __init ppc_corenet_clk_init(void)
-{
- return platform_driver_register(&ppc_corenet_clk_driver);
+ /* Check if this PLL is disabled */
+ if (mult & PLL_KILL) {
+ pr_debug("%s(): %s: Disabled\n", __func__, np->name);
+ return;
+ }
+ mult = (mult & GENMASK(6, 1)) >> 1;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+ if (!parent_name) {
+ pr_err("%s(): %s: of_clk_get_parent_name() failed\n",
+ __func__, np->name);
+ return;
+ }
+
+ i = of_property_count_strings(np, "clock-output-names");
+ if (i < 0) {
+ pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n",
+ __func__, np->name, i);
+ return;
+ }
+
+ cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL);
+ if (!cod)
+ return;
+ cod->clks = (struct clk **)(cod + 1);
+ cod->clk_num = i;
+
+ for (i = 0; i < cod->clk_num; i++) {
+ _errno = of_property_read_string_index(np, "clock-output-names",
+ i, &clk_name);
+ if (_errno < 0) {
+ pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n",
+ __func__, np->name, _errno);
+ goto return_clk_unregister;
+ }
+
+ cod->clks[i] = clk_register_fixed_factor(NULL, clk_name,
+ parent_name, 0, mult, 1 + i);
+ if (IS_ERR(cod->clks[i])) {
+ pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n",
+ __func__, np->name,
+ clk_name, PTR_ERR(cod->clks[i]));
+ goto return_clk_unregister;
+ }
+ }
+
+ _errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod);
+ if (_errno < 0) {
+ pr_err("%s(): %s: of_clk_add_provider() = %d\n",
+ __func__, np->name, _errno);
+ goto return_clk_unregister;
+ }
+
+ return;
+
+return_clk_unregister:
+ while (--i >= 0)
+ clk_unregister(cod->clks[i]);
+ kfree(cod);
}
-subsys_initcall(ppc_corenet_clk_init);
+
+CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
+CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
+CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
+CLK_OF_DECLARE(qoriq_core_pll_2, "fsl,qoriq-core-pll-2.0", core_pll_init);
+CLK_OF_DECLARE(qoriq_core_mux_1, "fsl,qoriq-core-mux-1.0", core_mux_init);
+CLK_OF_DECLARE(qoriq_core_mux_2, "fsl,qoriq-core-mux-2.0", core_mux_init);
+CLK_OF_DECLARE(qoriq_pltfrm_pll_1, "fsl,qoriq-platform-pll-1.0", pltfrm_pll_init);
+CLK_OF_DECLARE(qoriq_pltfrm_pll_2, "fsl,qoriq-platform-pll-2.0", pltfrm_pll_init);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 642cf37124d378..eb0152961d3c60 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -9,7 +9,7 @@
* Standard functionality for the common clock API. See Documentation/clk.txt
*/
-#include
+#include
#include
#include
#include
@@ -37,6 +37,55 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
+static long clk_core_get_accuracy(struct clk_core *clk);
+static unsigned long clk_core_get_rate(struct clk_core *clk);
+static int clk_core_get_phase(struct clk_core *clk);
+static bool clk_core_is_prepared(struct clk_core *clk);
+static bool clk_core_is_enabled(struct clk_core *clk);
+static struct clk_core *clk_core_lookup(const char *name);
+
+/*** private data structures ***/
+
+struct clk_core {
+ const char *name;
+ const struct clk_ops *ops;
+ struct clk_hw *hw;
+ struct module *owner;
+ struct clk_core *parent;
+ const char **parent_names;
+ struct clk_core **parents;
+ u8 num_parents;
+ u8 new_parent_index;
+ unsigned long rate;
+ unsigned long req_rate;
+ unsigned long new_rate;
+ struct clk_core *new_parent;
+ struct clk_core *new_child;
+ unsigned long flags;
+ unsigned int enable_count;
+ unsigned int prepare_count;
+ unsigned long accuracy;
+ int phase;
+ struct hlist_head children;
+ struct hlist_node child_node;
+ struct hlist_node debug_node;
+ struct hlist_head clks;
+ unsigned int notifier_count;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dentry;
+#endif
+ struct kref ref;
+};
+
+struct clk {
+ struct clk_core *core;
+ const char *dev_id;
+ const char *con_id;
+ unsigned long min_rate;
+ unsigned long max_rate;
+ struct hlist_node child_node;
+};
+
/*** locking ***/
static void clk_prepare_lock(void)
{
@@ -114,7 +163,8 @@ static struct hlist_head *orphan_list[] = {
NULL,
};
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+ int level)
{
if (!c)
return;
@@ -122,14 +172,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
level * 3 + 1, "",
30 - level * 3, c->name,
- c->enable_count, c->prepare_count, clk_get_rate(c),
- clk_get_accuracy(c), clk_get_phase(c));
+ c->enable_count, c->prepare_count, clk_core_get_rate(c),
+ clk_core_get_accuracy(c), clk_core_get_phase(c));
}
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -142,7 +192,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
static int clk_summary_show(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy phase\n");
@@ -172,7 +222,7 @@ static const struct file_operations clk_summary_fops = {
.release = single_release,
};
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -180,14 +230,14 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "\"%s\": { ", c->name);
seq_printf(s, "\"enable_count\": %d,", c->enable_count);
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
- seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
- seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
- seq_printf(s, "\"phase\": %d", clk_get_phase(c));
+ seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
+ seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
+ seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
}
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -204,7 +254,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
static int clk_dump(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
bool first_node = true;
struct hlist_head **lists = (struct hlist_head **)s->private;
@@ -240,7 +290,7 @@ static const struct file_operations clk_dump_fops = {
.release = single_release,
};
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
{
struct dentry *d;
int ret = -ENOMEM;
@@ -315,7 +365,7 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
* initialized. Otherwise it bails out early since the debugfs clk tree
* will be created lazily by clk_debug_init as part of a late_initcall.
*/
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
{
int ret = 0;
@@ -340,16 +390,12 @@ static int clk_debug_register(struct clk *clk)
* debugfs clk tree if clk->dentry points to debugfs created by
* clk_debug_register in __clk_init.
*/
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
{
mutex_lock(&clk_debug_lock);
- if (!clk->dentry)
- goto out;
-
hlist_del_init(&clk->debug_node);
debugfs_remove_recursive(clk->dentry);
clk->dentry = NULL;
-out:
mutex_unlock(&clk_debug_lock);
}
@@ -358,8 +404,9 @@ struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
{
struct dentry *d = NULL;
- if (hw->clk->dentry)
- d = debugfs_create_file(name, mode, hw->clk->dentry, data, fops);
+ if (hw->core->dentry)
+ d = debugfs_create_file(name, mode, hw->core->dentry, data,
+ fops);
return d;
}
@@ -379,7 +426,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
*/
static int __init clk_debug_init(void)
{
- struct clk *clk;
+ struct clk_core *clk;
struct dentry *d;
rootdir = debugfs_create_dir("clk", NULL);
@@ -418,22 +465,20 @@ static int __init clk_debug_init(void)
}
late_initcall(clk_debug_init);
#else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk,
+ struct clk_core *new_parent)
{
}
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
{
}
#endif
/* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
-
- if (!clk)
- return;
+ struct clk_core *child;
hlist_for_each_entry(child, &clk->children, child_node)
clk_unprepare_unused_subtree(child);
@@ -444,7 +489,7 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
if (clk->flags & CLK_IGNORE_UNUSED)
return;
- if (__clk_is_prepared(clk)) {
+ if (clk_core_is_prepared(clk)) {
if (clk->ops->unprepare_unused)
clk->ops->unprepare_unused(clk->hw);
else if (clk->ops->unprepare)
@@ -453,14 +498,11 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
}
/* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long flags;
- if (!clk)
- goto out;
-
hlist_for_each_entry(child, &clk->children, child_node)
clk_disable_unused_subtree(child);
@@ -477,7 +519,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
* sequence. call .disable_unused if available, otherwise fall
* back to .disable
*/
- if (__clk_is_enabled(clk)) {
+ if (clk_core_is_enabled(clk)) {
if (clk->ops->disable_unused)
clk->ops->disable_unused(clk->hw);
else if (clk->ops->disable)
@@ -486,9 +528,6 @@ static void clk_disable_unused_subtree(struct clk *clk)
unlock_out:
clk_enable_unlock(flags);
-
-out:
- return;
}
static bool clk_ignore_unused;
@@ -501,7 +540,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
static int clk_disable_unused(void)
{
- struct clk *clk;
+ struct clk_core *clk;
if (clk_ignore_unused) {
pr_warn("clk: Not disabling unused clocks\n");
@@ -532,48 +571,65 @@ late_initcall_sync(clk_disable_unused);
const char *__clk_get_name(struct clk *clk)
{
- return !clk ? NULL : clk->name;
+ return !clk ? NULL : clk->core->name;
}
EXPORT_SYMBOL_GPL(__clk_get_name);
struct clk_hw *__clk_get_hw(struct clk *clk)
{
- return !clk ? NULL : clk->hw;
+ return !clk ? NULL : clk->core->hw;
}
EXPORT_SYMBOL_GPL(__clk_get_hw);
u8 __clk_get_num_parents(struct clk *clk)
{
- return !clk ? 0 : clk->num_parents;
+ return !clk ? 0 : clk->core->num_parents;
}
EXPORT_SYMBOL_GPL(__clk_get_num_parents);
struct clk *__clk_get_parent(struct clk *clk)
{
- return !clk ? NULL : clk->parent;
+ if (!clk)
+ return NULL;
+
+ /* TODO: Create a per-user clk and change callers to call clk_put */
+ return !clk->core->parent ? NULL : clk->core->parent->hw->clk;
}
EXPORT_SYMBOL_GPL(__clk_get_parent);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+static struct clk_core *clk_core_get_parent_by_index(struct clk_core *clk,
+ u8 index)
{
if (!clk || index >= clk->num_parents)
return NULL;
else if (!clk->parents)
- return __clk_lookup(clk->parent_names[index]);
+ return clk_core_lookup(clk->parent_names[index]);
else if (!clk->parents[index])
return clk->parents[index] =
- __clk_lookup(clk->parent_names[index]);
+ clk_core_lookup(clk->parent_names[index]);
else
return clk->parents[index];
}
+
+struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+{
+ struct clk_core *parent;
+
+ if (!clk)
+ return NULL;
+
+ parent = clk_core_get_parent_by_index(clk->core, index);
+
+ return !parent ? NULL : parent->hw->clk;
+}
EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
unsigned int __clk_get_enable_count(struct clk *clk)
{
- return !clk ? 0 : clk->enable_count;
+ return !clk ? 0 : clk->core->enable_count;
}
-unsigned long __clk_get_rate(struct clk *clk)
+static unsigned long clk_core_get_rate_nolock(struct clk_core *clk)
{
unsigned long ret;
@@ -593,9 +649,17 @@ unsigned long __clk_get_rate(struct clk *clk)
out:
return ret;
}
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+ if (!clk)
+ return 0;
+
+ return clk_core_get_rate_nolock(clk->core);
+}
EXPORT_SYMBOL_GPL(__clk_get_rate);
-static unsigned long __clk_get_accuracy(struct clk *clk)
+static unsigned long __clk_get_accuracy(struct clk_core *clk)
{
if (!clk)
return 0;
@@ -605,11 +669,11 @@ static unsigned long __clk_get_accuracy(struct clk *clk)
unsigned long __clk_get_flags(struct clk *clk)
{
- return !clk ? 0 : clk->flags;
+ return !clk ? 0 : clk->core->flags;
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
-bool __clk_is_prepared(struct clk *clk)
+static bool clk_core_is_prepared(struct clk_core *clk)
{
int ret;
@@ -630,7 +694,15 @@ bool __clk_is_prepared(struct clk *clk)
return !!ret;
}
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_prepared(struct clk *clk)
+{
+ if (!clk)
+ return false;
+
+ return clk_core_is_prepared(clk->core);
+}
+
+static bool clk_core_is_enabled(struct clk_core *clk)
{
int ret;
@@ -650,12 +722,21 @@ bool __clk_is_enabled(struct clk *clk)
out:
return !!ret;
}
+
+bool __clk_is_enabled(struct clk *clk)
+{
+ if (!clk)
+ return false;
+
+ return clk_core_is_enabled(clk->core);
+}
EXPORT_SYMBOL_GPL(__clk_is_enabled);
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name,
+ struct clk_core *clk)
{
- struct clk *child;
- struct clk *ret;
+ struct clk_core *child;
+ struct clk_core *ret;
if (!strcmp(clk->name, name))
return clk;
@@ -669,10 +750,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
return NULL;
}
-struct clk *__clk_lookup(const char *name)
+static struct clk_core *clk_core_lookup(const char *name)
{
- struct clk *root_clk;
- struct clk *ret;
+ struct clk_core *root_clk;
+ struct clk_core *ret;
if (!name)
return NULL;
@@ -694,42 +775,53 @@ 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_hw **best_parent_p)
+static bool mux_is_better_rate(unsigned long rate, unsigned long now,
+ unsigned long best, unsigned long flags)
{
- struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+ if (flags & CLK_MUX_ROUND_CLOSEST)
+ return abs(now - rate) < abs(best - rate);
+
+ return now <= rate && now > best;
+}
+
+static long
+clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_p,
+ unsigned long flags)
+{
+ struct clk_core *core = hw->core, *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);
+ if (core->flags & CLK_SET_RATE_NO_REPARENT) {
+ parent = core->parent;
+ if (core->flags & CLK_SET_RATE_PARENT)
+ best = __clk_determine_rate(parent ? parent->hw : NULL,
+ rate, min_rate, max_rate);
else if (parent)
- best = __clk_get_rate(parent);
+ best = clk_core_get_rate_nolock(parent);
else
- best = __clk_get_rate(clk);
+ best = clk_core_get_rate_nolock(core);
goto out;
}
/* find the parent that can provide the fastest rate <= rate */
- num_parents = clk->num_parents;
+ num_parents = core->num_parents;
for (i = 0; i < num_parents; i++) {
- parent = clk_get_parent_by_index(clk, i);
+ parent = clk_core_get_parent_by_index(core, i);
if (!parent)
continue;
- if (clk->flags & CLK_SET_RATE_PARENT)
- parent_rate = __clk_round_rate(parent, rate);
+ if (core->flags & CLK_SET_RATE_PARENT)
+ parent_rate = __clk_determine_rate(parent->hw, rate,
+ min_rate,
+ max_rate);
else
- parent_rate = __clk_get_rate(parent);
- if (parent_rate <= rate && parent_rate > best) {
+ parent_rate = clk_core_get_rate_nolock(parent);
+ if (mux_is_better_rate(rate, parent_rate, best, flags)) {
best_parent = parent;
best = parent_rate;
}
@@ -742,11 +834,63 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
return best;
}
+
+struct clk *__clk_lookup(const char *name)
+{
+ struct clk_core *core = clk_core_lookup(name);
+
+ return !core ? NULL : core->hw->clk;
+}
+
+static void clk_core_get_boundaries(struct clk_core *clk,
+ unsigned long *min_rate,
+ unsigned long *max_rate)
+{
+ struct clk *clk_user;
+
+ *min_rate = 0;
+ *max_rate = ULONG_MAX;
+
+ hlist_for_each_entry(clk_user, &clk->clks, child_node)
+ *min_rate = max(*min_rate, clk_user->min_rate);
+
+ hlist_for_each_entry(clk_user, &clk->clks, child_node)
+ *max_rate = min(*max_rate, clk_user->max_rate);
+}
+
+/*
+ * 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 min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_p)
+{
+ return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
+ best_parent_rate,
+ best_parent_p, 0);
+}
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
+long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_p)
+{
+ return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
+ best_parent_rate,
+ best_parent_p,
+ CLK_MUX_ROUND_CLOSEST);
+}
+EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
+
/*** clk api ***/
-void __clk_unprepare(struct clk *clk)
+static void clk_core_unprepare(struct clk_core *clk)
{
if (!clk)
return;
@@ -762,7 +906,7 @@ void __clk_unprepare(struct clk *clk)
if (clk->ops->unprepare)
clk->ops->unprepare(clk->hw);
- __clk_unprepare(clk->parent);
+ clk_core_unprepare(clk->parent);
}
/**
@@ -782,12 +926,12 @@ void clk_unprepare(struct clk *clk)
return;
clk_prepare_lock();
- __clk_unprepare(clk);
+ clk_core_unprepare(clk->core);
clk_prepare_unlock();
}
EXPORT_SYMBOL_GPL(clk_unprepare);
-int __clk_prepare(struct clk *clk)
+static int clk_core_prepare(struct clk_core *clk)
{
int ret = 0;
@@ -795,14 +939,14 @@ int __clk_prepare(struct clk *clk)
return 0;
if (clk->prepare_count == 0) {
- ret = __clk_prepare(clk->parent);
+ ret = clk_core_prepare(clk->parent);
if (ret)
return ret;
if (clk->ops->prepare) {
ret = clk->ops->prepare(clk->hw);
if (ret) {
- __clk_unprepare(clk->parent);
+ clk_core_unprepare(clk->parent);
return ret;
}
}
@@ -829,15 +973,18 @@ int clk_prepare(struct clk *clk)
{
int ret;
+ if (!clk)
+ return 0;
+
clk_prepare_lock();
- ret = __clk_prepare(clk);
+ ret = clk_core_prepare(clk->core);
clk_prepare_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(clk_prepare);
-static void __clk_disable(struct clk *clk)
+static void clk_core_disable(struct clk_core *clk)
{
if (!clk)
return;
@@ -851,7 +998,15 @@ static void __clk_disable(struct clk *clk)
if (clk->ops->disable)
clk->ops->disable(clk->hw);
- __clk_disable(clk->parent);
+ clk_core_disable(clk->parent);
+}
+
+static void __clk_disable(struct clk *clk)
+{
+ if (!clk)
+ return;
+
+ clk_core_disable(clk->core);
}
/**
@@ -879,7 +1034,7 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_disable);
-static int __clk_enable(struct clk *clk)
+static int clk_core_enable(struct clk_core *clk)
{
int ret = 0;
@@ -890,7 +1045,7 @@ static int __clk_enable(struct clk *clk)
return -ESHUTDOWN;
if (clk->enable_count == 0) {
- ret = __clk_enable(clk->parent);
+ ret = clk_core_enable(clk->parent);
if (ret)
return ret;
@@ -898,7 +1053,7 @@ static int __clk_enable(struct clk *clk)
if (clk->ops->enable) {
ret = clk->ops->enable(clk->hw);
if (ret) {
- __clk_disable(clk->parent);
+ clk_core_disable(clk->parent);
return ret;
}
}
@@ -908,6 +1063,14 @@ static int __clk_enable(struct clk *clk)
return 0;
}
+static int __clk_enable(struct clk *clk)
+{
+ if (!clk)
+ return 0;
+
+ return clk_core_enable(clk->core);
+}
+
/**
* clk_enable - ungate a clock
* @clk: the clk being ungated
@@ -934,17 +1097,13 @@ int clk_enable(struct clk *clk)
}
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)
+static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+ unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate)
{
unsigned long parent_rate = 0;
- struct clk *parent;
+ struct clk_core *parent;
struct clk_hw *parent_hw;
if (!clk)
@@ -956,15 +1115,59 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
if (clk->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
- return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
- &parent_hw);
+ return clk->ops->determine_rate(clk->hw, rate,
+ min_rate, max_rate,
+ &parent_rate, &parent_hw);
} 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);
+ return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+ max_rate);
else
return clk->rate;
}
+
+/**
+ * __clk_determine_rate - get the closest rate actually supported by a clock
+ * @hw: determine the rate of this clock
+ * @rate: target rate
+ * @min_rate: returned rate must be greater than this rate
+ * @max_rate: returned rate must be less than this rate
+ *
+ * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate and
+ * .determine_rate.
+ */
+unsigned long __clk_determine_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate)
+{
+ if (!hw)
+ return 0;
+
+ return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+}
+EXPORT_SYMBOL_GPL(__clk_determine_rate);
+
+/**
+ * __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 min_rate;
+ unsigned long max_rate;
+
+ if (!clk)
+ return 0;
+
+ clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+
+ return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
+}
EXPORT_SYMBOL_GPL(__clk_round_rate);
/**
@@ -980,6 +1183,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
{
unsigned long ret;
+ if (!clk)
+ return 0;
+
clk_prepare_lock();
ret = __clk_round_rate(clk, rate);
clk_prepare_unlock();
@@ -1002,22 +1208,21 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
* called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
* a driver returns that.
*/
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
struct clk_notifier *cn;
struct clk_notifier_data cnd;
int ret = NOTIFY_DONE;
- cnd.clk = clk;
cnd.old_rate = old_rate;
cnd.new_rate = new_rate;
list_for_each_entry(cn, &clk_notifier_list, node) {
- if (cn->clk == clk) {
+ if (cn->clk->core == clk) {
+ cnd.clk = cn->clk;
ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
&cnd);
- break;
}
}
@@ -1035,10 +1240,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
{
unsigned long parent_accuracy = 0;
- struct clk *child;
+ struct clk_core *child;
if (clk->parent)
parent_accuracy = clk->parent->accuracy;
@@ -1053,6 +1258,20 @@ static void __clk_recalc_accuracies(struct clk *clk)
__clk_recalc_accuracies(child);
}
+static long clk_core_get_accuracy(struct clk_core *clk)
+{
+ unsigned long accuracy;
+
+ clk_prepare_lock();
+ if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
+ __clk_recalc_accuracies(clk);
+
+ accuracy = __clk_get_accuracy(clk);
+ clk_prepare_unlock();
+
+ return accuracy;
+}
+
/**
* clk_get_accuracy - return the accuracy of clk
* @clk: the clk whose accuracy is being returned
@@ -1064,20 +1283,15 @@ static void __clk_recalc_accuracies(struct clk *clk)
*/
long clk_get_accuracy(struct clk *clk)
{
- unsigned long accuracy;
-
- clk_prepare_lock();
- if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
- __clk_recalc_accuracies(clk);
-
- accuracy = __clk_get_accuracy(clk);
- clk_prepare_unlock();
+ if (!clk)
+ return 0;
- return accuracy;
+ return clk_core_get_accuracy(clk->core);
}
EXPORT_SYMBOL_GPL(clk_get_accuracy);
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk,
+ unsigned long parent_rate)
{
if (clk->ops->recalc_rate)
return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1098,11 +1312,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
{
unsigned long old_rate;
unsigned long parent_rate = 0;
- struct clk *child;
+ struct clk_core *child;
old_rate = clk->rate;
@@ -1122,15 +1336,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
__clk_recalc_rates(child, msg);
}
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+static unsigned long clk_core_get_rate(struct clk_core *clk)
{
unsigned long rate;
@@ -1139,14 +1345,32 @@ unsigned long clk_get_rate(struct clk *clk)
if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
__clk_recalc_rates(clk, 0);
- rate = __clk_get_rate(clk);
+ rate = clk_core_get_rate_nolock(clk);
clk_prepare_unlock();
return rate;
}
+EXPORT_SYMBOL_GPL(clk_core_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (!clk)
+ return 0;
+
+ return clk_core_get_rate(clk->core);
+}
EXPORT_SYMBOL_GPL(clk_get_rate);
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk,
+ struct clk_core *parent)
{
int i;
@@ -1160,7 +1384,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
/*
* 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.
+ * them now to avoid future calls to clk_core_lookup.
*/
for (i = 0; i < clk->num_parents; i++) {
if (clk->parents[i] == parent)
@@ -1170,7 +1394,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
continue;
if (!strcmp(clk->parent_names[i], parent->name)) {
- clk->parents[i] = __clk_lookup(parent->name);
+ clk->parents[i] = clk_core_lookup(parent->name);
return i;
}
}
@@ -1178,7 +1402,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
return -EINVAL;
}
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
{
hlist_del(&clk->child_node);
@@ -1195,10 +1419,11 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
clk->parent = new_parent;
}
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+ struct clk_core *parent)
{
unsigned long flags;
- struct clk *old_parent = clk->parent;
+ struct clk_core *old_parent = clk->parent;
/*
* Migrate prepare state between parents and prevent race with
@@ -1218,9 +1443,9 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
* See also: Comment for clk_set_parent() below.
*/
if (clk->prepare_count) {
- __clk_prepare(parent);
- clk_enable(parent);
- clk_enable(clk);
+ clk_core_prepare(parent);
+ clk_core_enable(parent);
+ clk_core_enable(clk);
}
/* update the clk tree topology */
@@ -1231,25 +1456,27 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
return old_parent;
}
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
- struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *core,
+ struct clk_core *parent,
+ struct clk_core *old_parent)
{
/*
* 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);
+ if (core->prepare_count) {
+ clk_core_disable(core);
+ clk_core_disable(old_parent);
+ clk_core_unprepare(old_parent);
}
}
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+ u8 p_index)
{
unsigned long flags;
int ret = 0;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_parent = __clk_set_parent_before(clk, parent);
@@ -1263,9 +1490,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
clk_enable_unlock(flags);
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(parent);
- __clk_unprepare(parent);
+ clk_core_disable(clk);
+ clk_core_disable(parent);
+ clk_core_unprepare(parent);
}
return ret;
}
@@ -1291,9 +1518,10 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
*
* Caller must hold prepare_lock.
*/
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk,
+ unsigned long parent_rate)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long new_rate;
int ret = NOTIFY_DONE;
@@ -1319,10 +1547,10 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
return ret;
}
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
- struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+ struct clk_core *new_parent, u8 p_index)
{
- struct clk *child;
+ struct clk_core *child;
clk->new_rate = new_rate;
clk->new_parent = new_parent;
@@ -1342,13 +1570,16 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
* calculate the new rates returning the topmost clock that has to be
* changed.
*/
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+ unsigned long rate)
{
- struct clk *top = clk;
- struct clk *old_parent, *parent;
+ struct clk_core *top = clk;
+ struct clk_core *old_parent, *parent;
struct clk_hw *parent_hw;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
+ unsigned long min_rate;
+ unsigned long max_rate;
int p_index = 0;
/* sanity */
@@ -1360,16 +1591,22 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
if (parent)
best_parent_rate = parent->rate;
+ clk_core_get_boundaries(clk, &min_rate, &max_rate);
+
/* find the closest rate and parent clk/rate */
if (clk->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
new_rate = clk->ops->determine_rate(clk->hw, rate,
+ min_rate,
+ max_rate,
&best_parent_rate,
&parent_hw);
- parent = parent_hw ? parent_hw->clk : NULL;
+ parent = parent_hw ? parent_hw->core : NULL;
} else if (clk->ops->round_rate) {
new_rate = clk->ops->round_rate(clk->hw, rate,
&best_parent_rate);
+ if (new_rate < min_rate || new_rate > max_rate)
+ return NULL;
} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
/* pass-through clock without adjustable parent */
clk->new_rate = clk->rate;
@@ -1390,7 +1627,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
}
/* try finding the new parent index */
- if (parent) {
+ if (parent && clk->num_parents > 1) {
p_index = clk_fetch_parent_index(clk, parent);
if (p_index < 0) {
pr_debug("%s: clk %s can not be parent of clk %s\n",
@@ -1414,9 +1651,10 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
* so that in case of an error we can walk down the whole tree again and
* abort the change.
*/
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+ unsigned long event)
{
- struct clk *child, *tmp_clk, *fail_clk = NULL;
+ struct clk_core *child, *tmp_clk, *fail_clk = NULL;
int ret = NOTIFY_DONE;
if (clk->rate == clk->new_rate)
@@ -1451,14 +1689,14 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
* walk down a subtree and set the new rates notifying the rate
* change on the way
*/
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
struct hlist_node *tmp;
unsigned long old_rate;
unsigned long best_parent_rate = 0;
bool skip_set_rate = false;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_rate = clk->rate;
@@ -1506,6 +1744,45 @@ static void clk_change_rate(struct clk *clk)
clk_change_rate(clk->new_child);
}
+static int clk_core_set_rate_nolock(struct clk_core *clk,
+ unsigned long req_rate)
+{
+ struct clk_core *top, *fail_clk;
+ unsigned long rate = req_rate;
+ int ret = 0;
+
+ if (!clk)
+ return 0;
+
+ /* bail early if nothing to do */
+ if (rate == clk_core_get_rate_nolock(clk))
+ return 0;
+
+ if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+ return -EBUSY;
+
+ /* calculate new rates and get the topmost changed clock */
+ top = clk_calc_new_rates(clk, rate);
+ if (!top)
+ return -EINVAL;
+
+ /* notify that we are about to change rates */
+ fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
+ if (fail_clk) {
+ pr_debug("%s: failed to set %s rate\n", __func__,
+ fail_clk->name);
+ clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
+ return -EBUSY;
+ }
+
+ /* change the rates */
+ clk_change_rate(top);
+
+ clk->req_rate = req_rate;
+
+ return ret;
+}
+
/**
* clk_set_rate - specify a new rate for clk
* @clk: the clk whose rate is being changed
@@ -1529,8 +1806,7 @@ static void clk_change_rate(struct clk *clk)
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
- struct clk *top, *fail_clk;
- int ret = 0;
+ int ret;
if (!clk)
return 0;
@@ -1538,41 +1814,81 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
/* prevent racing with updates to the clock topology */
clk_prepare_lock();
- /* bail early if nothing to do */
- if (rate == clk_get_rate(clk))
- goto out;
+ ret = clk_core_set_rate_nolock(clk->core, rate);
- if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
- ret = -EBUSY;
- goto out;
- }
+ clk_prepare_unlock();
- /* calculate new rates and get the topmost changed clock */
- top = clk_calc_new_rates(clk, rate);
- if (!top) {
- ret = -EINVAL;
- goto out;
- }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
- /* notify that we are about to change rates */
- fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
- if (fail_clk) {
- pr_debug("%s: failed to set %s rate\n", __func__,
- fail_clk->name);
- clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
- ret = -EBUSY;
- goto out;
+/**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+{
+ int ret = 0;
+
+ if (!clk)
+ return 0;
+
+ if (min > max) {
+ pr_err("%s: clk %s dev %s con %s: invalid range [%lu, %lu]\n",
+ __func__, clk->core->name, clk->dev_id, clk->con_id,
+ min, max);
+ return -EINVAL;
}
- /* change the rates */
- clk_change_rate(top);
+ clk_prepare_lock();
+
+ if (min != clk->min_rate || max != clk->max_rate) {
+ clk->min_rate = min;
+ clk->max_rate = max;
+ ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+ }
-out:
clk_prepare_unlock();
return ret;
}
-EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_set_rate_range);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate)
+{
+ if (!clk)
+ return 0;
+
+ return clk_set_rate_range(clk, rate, clk->max_rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_min_rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate)
+{
+ if (!clk)
+ return 0;
+
+ return clk_set_rate_range(clk, clk->min_rate, rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_max_rate);
/**
* clk_get_parent - return the parent of a clk
@@ -1599,11 +1915,11 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
*
* For single-parent clocks without .get_parent, first check to see if the
* .parents array exists, and if so use it to avoid an expensive tree
- * traversal. If .parents does not exist then walk the tree with __clk_lookup.
+ * traversal. If .parents does not exist then walk the tree.
*/
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
{
- struct clk *ret = NULL;
+ struct clk_core *ret = NULL;
u8 index;
/* handle the trivial cases */
@@ -1613,7 +1929,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
if (clk->num_parents == 1) {
if (IS_ERR_OR_NULL(clk->parent))
- clk->parent = __clk_lookup(clk->parent_names[0]);
+ clk->parent = clk_core_lookup(clk->parent_names[0]);
ret = clk->parent;
goto out;
}
@@ -1627,8 +1943,8 @@ static struct clk *__clk_init_parent(struct clk *clk)
/*
* Do our best to cache parent clocks in clk->parents. This prevents
- * unnecessary and expensive calls to __clk_lookup. We don't set
- * clk->parent here; that is done by the calling function
+ * unnecessary and expensive lookups. We don't set clk->parent here;
+ * that is done by the calling function.
*/
index = clk->ops->get_parent(clk->hw);
@@ -1638,13 +1954,14 @@ static struct clk *__clk_init_parent(struct clk *clk)
kcalloc(clk->num_parents, sizeof(struct clk *),
GFP_KERNEL);
- ret = clk_get_parent_by_index(clk, index);
+ ret = clk_core_get_parent_by_index(clk, index);
out:
return ret;
}
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_core_reparent(struct clk_core *clk,
+ struct clk_core *new_parent)
{
clk_reparent(clk, new_parent);
__clk_recalc_accuracies(clk);
@@ -1652,23 +1969,40 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent)
}
/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
+ * clk_has_parent - check if a clock is a possible parent for another
+ * @clk: clock source
+ * @parent: parent clock source
*
- * Re-parent clk to use parent as its new input source. If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
+ * This function can be used in drivers that need to check that a clock can be
+ * the parent of another without actually changing the parent.
*
- * Returns 0 on success, -EERROR otherwise.
+ * Returns true if @parent is a possible parent for @clk, false otherwise.
*/
-int clk_set_parent(struct clk *clk, struct clk *parent)
+bool clk_has_parent(struct clk *clk, struct clk *parent)
+{
+ struct clk_core *core, *parent_core;
+ unsigned int i;
+
+ /* NULL clocks should be nops, so return success if either is NULL. */
+ if (!clk || !parent)
+ return true;
+
+ core = clk->core;
+ parent_core = parent->core;
+
+ /* Optimize for the case where the parent is already the parent. */
+ if (core->parent == parent_core)
+ return true;
+
+ for (i = 0; i < core->num_parents; i++)
+ if (strcmp(core->parent_names[i], parent_core->name) == 0)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(clk_has_parent);
+
+static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
{
int ret = 0;
int p_index = 0;
@@ -1728,6 +2062,31 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
return ret;
}
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source. If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ if (!clk)
+ return 0;
+
+ return clk_core_set_parent(clk->core, parent ? parent->core : NULL);
+}
EXPORT_SYMBOL_GPL(clk_set_parent);
/**
@@ -1764,13 +2123,13 @@ int clk_set_phase(struct clk *clk, int degrees)
clk_prepare_lock();
- if (!clk->ops->set_phase)
+ if (!clk->core->ops->set_phase)
goto out_unlock;
- ret = clk->ops->set_phase(clk->hw, degrees);
+ ret = clk->core->ops->set_phase(clk->core->hw, degrees);
if (!ret)
- clk->phase = degrees;
+ clk->core->phase = degrees;
out_unlock:
clk_prepare_unlock();
@@ -1778,15 +2137,9 @@ int clk_set_phase(struct clk *clk, int degrees)
out:
return ret;
}
+EXPORT_SYMBOL_GPL(clk_set_phase);
-/**
- * clk_get_phase - return the phase shift of a clock signal
- * @clk: clock signal source
- *
- * Returns the phase shift of a clock node in degrees, otherwise returns
- * -EERROR.
- */
-int clk_get_phase(struct clk *clk)
+static int clk_core_get_phase(struct clk_core *clk)
{
int ret = 0;
@@ -1800,28 +2153,48 @@ int clk_get_phase(struct clk *clk)
out:
return ret;
}
+EXPORT_SYMBOL_GPL(clk_get_phase);
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+ if (!clk)
+ return 0;
+
+ return clk_core_get_phase(clk->core);
+}
/**
* __clk_init - initialize the data structures in a struct clk
* @dev: device initializing this clk, placeholder for now
* @clk: clk being initialized
*
- * Initializes the lists in struct clk, queries the hardware for the
+ * Initializes the lists in struct clk_core, queries the hardware for the
* parent and rate and sets them both.
*/
-int __clk_init(struct device *dev, struct clk *clk)
+static int __clk_init(struct device *dev, struct clk *clk_user)
{
int i, ret = 0;
- struct clk *orphan;
+ struct clk_core *orphan;
struct hlist_node *tmp2;
+ struct clk_core *clk;
+ unsigned long rate;
- if (!clk)
+ if (!clk_user)
return -EINVAL;
+ clk = clk_user->core;
+
clk_prepare_lock();
/* check to see if a clock with this name is already registered */
- if (__clk_lookup(clk->name)) {
+ if (clk_core_lookup(clk->name)) {
pr_debug("%s: clk %s already initialized\n",
__func__, clk->name);
ret = -EEXIST;
@@ -1873,7 +2246,7 @@ int __clk_init(struct device *dev, struct clk *clk)
clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
GFP_KERNEL);
/*
- * __clk_lookup returns NULL for parents that have not been
+ * clk_core_lookup returns NULL for parents that have not been
* clk_init'd; thus any access to clk->parents[] must check
* for a NULL pointer. We can always perform lazy lookups for
* missing parents later on.
@@ -1881,7 +2254,7 @@ int __clk_init(struct device *dev, struct clk *clk)
if (clk->parents)
for (i = 0; i < clk->num_parents; i++)
clk->parents[i] =
- __clk_lookup(clk->parent_names[i]);
+ clk_core_lookup(clk->parent_names[i]);
}
clk->parent = __clk_init_parent(clk);
@@ -1936,12 +2309,13 @@ int __clk_init(struct device *dev, struct clk *clk)
* then rate is set to zero.
*/
if (clk->ops->recalc_rate)
- clk->rate = clk->ops->recalc_rate(clk->hw,
- __clk_get_rate(clk->parent));
+ rate = clk->ops->recalc_rate(clk->hw,
+ clk_core_get_rate_nolock(clk->parent));
else if (clk->parent)
- clk->rate = clk->parent->rate;
+ rate = clk->parent->rate;
else
- clk->rate = 0;
+ rate = 0;
+ clk->rate = clk->req_rate = rate;
/*
* walk the list of orphan clocks and reparent any that are children of
@@ -1951,13 +2325,13 @@ int __clk_init(struct device *dev, struct clk *clk)
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);
+ clk_core_reparent(orphan, clk);
continue;
}
for (i = 0; i < orphan->num_parents; i++)
if (!strcmp(clk->name, orphan->parent_names[i])) {
- __clk_reparent(orphan, clk);
+ clk_core_reparent(orphan, clk);
break;
}
}
@@ -1983,47 +2357,39 @@ int __clk_init(struct device *dev, struct clk *clk)
return ret;
}
-/**
- * __clk_register - register a clock and return a cookie.
- *
- * Same as clk_register, except that the .clk field inside hw shall point to a
- * preallocated (generally statically allocated) struct clk. None of the fields
- * of the struct clk need to be initialized.
- *
- * The data pointed to by .init and .clk field shall NOT be marked as init
- * data.
- *
- * __clk_register is only exposed via clk-private.h and is intended for use with
- * 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 its operations. Returns 0
- * on success, otherwise an error code.
- */
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
+struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
+ const char *con_id)
{
- int ret;
struct clk *clk;
- clk = hw->clk;
- clk->name = hw->init->name;
- clk->ops = hw->init->ops;
- clk->hw = hw;
- clk->flags = hw->init->flags;
- clk->parent_names = hw->init->parent_names;
- clk->num_parents = hw->init->num_parents;
- if (dev && dev->driver)
- clk->owner = dev->driver->owner;
- else
- clk->owner = NULL;
+ /* This is to allow this function to be chained to others */
+ if (!hw || IS_ERR(hw))
+ return (struct clk *) hw;
- ret = __clk_init(dev, clk);
- if (ret)
- return ERR_PTR(ret);
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->core = hw->core;
+ clk->dev_id = dev_id;
+ clk->con_id = con_id;
+ clk->max_rate = ULONG_MAX;
+
+ clk_prepare_lock();
+ hlist_add_head(&clk->child_node, &hw->core->clks);
+ clk_prepare_unlock();
return clk;
}
-EXPORT_SYMBOL_GPL(__clk_register);
+
+void __clk_free_clk(struct clk *clk)
+{
+ clk_prepare_lock();
+ hlist_del(&clk->child_node);
+ clk_prepare_unlock();
+
+ kfree(clk);
+}
/**
* clk_register - allocate a new clock, register it and return an opaque cookie
@@ -2039,7 +2405,7 @@ EXPORT_SYMBOL_GPL(__clk_register);
struct clk *clk_register(struct device *dev, struct clk_hw *hw)
{
int i, ret;
- struct clk *clk;
+ struct clk_core *clk;
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
if (!clk) {
@@ -2060,7 +2426,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
clk->hw = hw;
clk->flags = hw->init->flags;
clk->num_parents = hw->init->num_parents;
- hw->clk = clk;
+ hw->core = clk;
/* allocate local copy in case parent_names is __initdata */
clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
@@ -2084,9 +2450,21 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
}
}
- ret = __clk_init(dev, clk);
+ INIT_HLIST_HEAD(&clk->clks);
+
+ hw->clk = __clk_create_clk(hw, NULL, NULL);
+ if (IS_ERR(hw->clk)) {
+ pr_err("%s: could not allocate per-user clk\n", __func__);
+ ret = PTR_ERR(hw->clk);
+ goto fail_parent_names_copy;
+ }
+
+ ret = __clk_init(dev, hw->clk);
if (!ret)
- return clk;
+ return hw->clk;
+
+ __clk_free_clk(hw->clk);
+ hw->clk = NULL;
fail_parent_names_copy:
while (--i >= 0)
@@ -2107,7 +2485,7 @@ EXPORT_SYMBOL_GPL(clk_register);
*/
static void __clk_release(struct kref *ref)
{
- struct clk *clk = container_of(ref, struct clk, ref);
+ struct clk_core *clk = container_of(ref, struct clk_core, ref);
int i = clk->num_parents;
kfree(clk->parents);
@@ -2165,12 +2543,13 @@ void clk_unregister(struct clk *clk)
if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
return;
- clk_debug_unregister(clk);
+ clk_debug_unregister(clk->core);
clk_prepare_lock();
- if (clk->ops == &clk_nodrv_ops) {
- pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
+ if (clk->core->ops == &clk_nodrv_ops) {
+ pr_err("%s: unregistered clock: %s\n", __func__,
+ clk->core->name);
return;
}
/*
@@ -2178,24 +2557,25 @@ void clk_unregister(struct clk *clk)
* a reference to this clock.
*/
flags = clk_enable_lock();
- clk->ops = &clk_nodrv_ops;
+ clk->core->ops = &clk_nodrv_ops;
clk_enable_unlock(flags);
- if (!hlist_empty(&clk->children)) {
- struct clk *child;
+ if (!hlist_empty(&clk->core->children)) {
+ struct clk_core *child;
struct hlist_node *t;
/* Reparent all children to the orphan list. */
- hlist_for_each_entry_safe(child, t, &clk->children, child_node)
- clk_set_parent(child, NULL);
+ hlist_for_each_entry_safe(child, t, &clk->core->children,
+ child_node)
+ clk_core_set_parent(child, NULL);
}
- hlist_del_init(&clk->child_node);
+ hlist_del_init(&clk->core->child_node);
- if (clk->prepare_count)
+ if (clk->core->prepare_count)
pr_warn("%s: unregistering prepared clock: %s\n",
- __func__, clk->name);
- kref_put(&clk->ref, __clk_release);
+ __func__, clk->core->name);
+ kref_put(&clk->core->ref, __clk_release);
clk_prepare_unlock();
}
@@ -2263,11 +2643,13 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
*/
int __clk_get(struct clk *clk)
{
- if (clk) {
- if (!try_module_get(clk->owner))
+ struct clk_core *core = !clk ? NULL : clk->core;
+
+ if (core) {
+ if (!try_module_get(core->owner))
return 0;
- kref_get(&clk->ref);
+ kref_get(&core->ref);
}
return 1;
}
@@ -2280,11 +2662,20 @@ void __clk_put(struct clk *clk)
return;
clk_prepare_lock();
- owner = clk->owner;
- kref_put(&clk->ref, __clk_release);
+
+ hlist_del(&clk->child_node);
+ if (clk->min_rate > clk->core->req_rate ||
+ clk->max_rate < clk->core->req_rate)
+ clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+
+ owner = clk->core->owner;
+ kref_put(&clk->core->ref, __clk_release);
+
clk_prepare_unlock();
module_put(owner);
+
+ kfree(clk);
}
/*** clk rate change notifiers ***/
@@ -2339,7 +2730,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
- clk->notifier_count++;
+ clk->core->notifier_count++;
out:
clk_prepare_unlock();
@@ -2376,7 +2767,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
if (cn->clk == clk) {
ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
- clk->notifier_count--;
+ clk->core->notifier_count--;
/* XXX the notifier code should handle this better */
if (!cn->notifier_head.head) {
@@ -2506,7 +2897,8 @@ void of_clk_del_provider(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_clk_del_provider);
-struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
+struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
+ const char *dev_id, const char *con_id)
{
struct of_clk_provider *provider;
struct clk *clk = ERR_PTR(-EPROBE_DEFER);
@@ -2515,8 +2907,17 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
list_for_each_entry(provider, &of_clk_providers, link) {
if (provider->node == clkspec->np)
clk = provider->get(clkspec, provider->data);
- if (!IS_ERR(clk))
+ if (!IS_ERR(clk)) {
+ clk = __clk_create_clk(__clk_get_hw(clk), dev_id,
+ con_id);
+
+ if (!IS_ERR(clk) && !__clk_get(clk)) {
+ __clk_free_clk(clk);
+ clk = ERR_PTR(-ENOENT);
+ }
+
break;
+ }
}
return clk;
@@ -2527,7 +2928,7 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
struct clk *clk;
mutex_lock(&of_clk_mutex);
- clk = __of_clk_get_from_provider(clkspec);
+ clk = __of_clk_get_from_provider(clkspec, NULL, __func__);
mutex_unlock(&of_clk_mutex);
return clk;
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index c798138f023f6a..ba845408cc3e85 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,31 @@
* published by the Free Software Foundation.
*/
+struct clk_hw;
+
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
-struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
+struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
+ const char *dev_id, const char *con_id);
void of_clk_lock(void);
void of_clk_unlock(void);
#endif
+
+#ifdef CONFIG_COMMON_CLK
+struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
+ const char *con_id);
+void __clk_free_clk(struct clk *clk);
+#else
+/* All these casts to avoid ifdefs in clkdev... */
+static inline struct clk *
+__clk_create_clk(struct clk_hw *hw, const char *dev_id, const char *con_id)
+{
+ return (struct clk *)hw;
+}
+static inline void __clk_free_clk(struct clk *clk) { }
+static struct clk_hw *__clk_get_hw(struct clk *clk)
+{
+ return (struct clk_hw *)clk;
+}
+
+#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8b7fc7e9..043fd363337398 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include "clk.h"
@@ -28,6 +29,20 @@ static DEFINE_MUTEX(clocks_mutex);
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
+static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
+ const char *dev_id, const char *con_id)
+{
+ struct clk *clk;
+
+ if (!clkspec)
+ return ERR_PTR(-EINVAL);
+
+ of_clk_lock();
+ clk = __of_clk_get_from_provider(clkspec, dev_id, con_id);
+ of_clk_unlock();
+ return clk;
+}
+
/**
* of_clk_get_by_clkspec() - Lookup a clock form a clock provider
* @clkspec: pointer to a clock specifier data structure
@@ -38,22 +53,11 @@ static DEFINE_MUTEX(clocks_mutex);
*/
struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
{
- struct clk *clk;
-
- if (!clkspec)
- return ERR_PTR(-EINVAL);
-
- of_clk_lock();
- clk = __of_clk_get_from_provider(clkspec);
-
- if (!IS_ERR(clk) && !__clk_get(clk))
- clk = ERR_PTR(-ENOENT);
-
- of_clk_unlock();
- return clk;
+ return __of_clk_get_by_clkspec(clkspec, NULL, __func__);
}
-struct clk *of_clk_get(struct device_node *np, int index)
+static struct clk *__of_clk_get(struct device_node *np, int index,
+ const char *dev_id, const char *con_id)
{
struct of_phandle_args clkspec;
struct clk *clk;
@@ -67,22 +71,21 @@ struct clk *of_clk_get(struct device_node *np, int index)
if (rc)
return ERR_PTR(rc);
- clk = of_clk_get_by_clkspec(&clkspec);
+ clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
of_node_put(clkspec.np);
+
return clk;
}
+
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+ return __of_clk_get(np, index, np->full_name, NULL);
+}
EXPORT_SYMBOL(of_clk_get);
-/**
- * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
- * @np: pointer to clock consumer node
- * @name: name of consumer's clock input, or NULL for the first clock reference
- *
- * This function parses the clocks and clock-names properties,
- * and uses them to look up the struct clk from the registered list of clock
- * providers.
- */
-struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+static struct clk *__of_clk_get_by_name(struct device_node *np,
+ const char *dev_id,
+ const char *name)
{
struct clk *clk = ERR_PTR(-ENOENT);
@@ -97,10 +100,10 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
*/
if (name)
index = of_property_match_string(np, "clock-names", name);
- clk = of_clk_get(np, index);
- if (!IS_ERR(clk))
+ clk = __of_clk_get(np, index, dev_id, name);
+ if (!IS_ERR(clk)) {
break;
- else if (name && index >= 0) {
+ } else if (name && index >= 0) {
if (PTR_ERR(clk) != -EPROBE_DEFER)
pr_err("ERROR: could not get clock %s:%s(%i)\n",
np->full_name, name ? name : "", index);
@@ -119,7 +122,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
return clk;
}
+
+/**
+ * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the struct clk from the registered list of clock
+ * providers.
+ */
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+ if (!np)
+ return ERR_PTR(-ENOENT);
+
+ return __of_clk_get_by_name(np, np->full_name, name);
+}
EXPORT_SYMBOL(of_clk_get_by_name);
+
+#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
+
+static struct clk *__of_clk_get_by_name(struct device_node *np,
+ const char *dev_id,
+ const char *name)
+{
+ return ERR_PTR(-ENOENT);
+}
#endif
/*
@@ -168,14 +197,28 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{
struct clk_lookup *cl;
+ struct clk *clk = NULL;
mutex_lock(&clocks_mutex);
+
cl = clk_find(dev_id, con_id);
- if (cl && !__clk_get(cl->clk))
+ if (!cl)
+ goto out;
+
+ clk = __clk_create_clk(__clk_get_hw(cl->clk), dev_id, con_id);
+ if (IS_ERR(clk))
+ goto out;
+
+ if (!__clk_get(clk)) {
+ __clk_free_clk(clk);
cl = NULL;
+ goto out;
+ }
+
+out:
mutex_unlock(&clocks_mutex);
- return cl ? cl->clk : ERR_PTR(-ENOENT);
+ return cl ? clk : ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(clk_get_sys);
@@ -185,10 +228,8 @@ struct clk *clk_get(struct device *dev, const char *con_id)
struct clk *clk;
if (dev) {
- clk = of_clk_get_by_name(dev->of_node, con_id);
- if (!IS_ERR(clk))
- return clk;
- if (PTR_ERR(clk) == -EPROBE_DEFER)
+ clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+ if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
@@ -331,6 +372,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
return 0;
}
+EXPORT_SYMBOL(clk_register_clkdev);
/**
* clk_register_clkdevs - register a set of clk_lookup for a struct clk
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 007144f81f50b6..2e4f6d432bebeb 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -295,6 +295,8 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
}
static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p)
{
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
index 48fa53c7ce5e0d..de6a873175d2b8 100644
--- a/drivers/clk/mmp/clk-mix.c
+++ b/drivers/clk/mmp/clk-mix.c
@@ -202,6 +202,8 @@ static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val,
}
static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
diff --git a/drivers/clk/pxa/Makefile b/drivers/clk/pxa/Makefile
index 38e9153446059a..38e37bf6b821d8 100644
--- a/drivers/clk/pxa/Makefile
+++ b/drivers/clk/pxa/Makefile
@@ -1,3 +1,4 @@
obj-y += clk-pxa.o
obj-$(CONFIG_PXA25x) += clk-pxa25x.o
obj-$(CONFIG_PXA27x) += clk-pxa27x.o
+obj-$(CONFIG_PXA3xx) += clk-pxa3xx.o
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c
index 4e834753ab0945..29cee9e8d4d91b 100644
--- a/drivers/clk/pxa/clk-pxa.c
+++ b/drivers/clk/pxa/clk-pxa.c
@@ -46,7 +46,7 @@ static unsigned long cken_recalc_rate(struct clk_hw *hw,
fix = &pclk->lp;
else
fix = &pclk->hp;
- fix->hw.clk = hw->clk;
+ __clk_hw_set_clk(&fix->hw, hw);
return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate);
}
diff --git a/drivers/clk/pxa/clk-pxa3xx.c b/drivers/clk/pxa/clk-pxa3xx.c
new file mode 100644
index 00000000000000..39f891bba09a99
--- /dev/null
+++ b/drivers/clk/pxa/clk-pxa3xx.c
@@ -0,0 +1,364 @@
+/*
+ * Marvell PXA3xxx family clocks
+ *
+ * Copyright (C) 2014 Robert Jarzmik
+ *
+ * Heavily inspired from former arch/arm/mach-pxa/pxa3xx.c
+ *
+ * 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; version 2 of the License.
+ *
+ * For non-devicetree platforms. Once pxa is fully converted to devicetree, this
+ * should go away.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include "clk-pxa.h"
+
+#define KHz 1000
+#define MHz (1000 * 1000)
+
+enum {
+ PXA_CORE_60Mhz = 0,
+ PXA_CORE_RUN,
+ PXA_CORE_TURBO,
+};
+
+enum {
+ PXA_BUS_60Mhz = 0,
+ PXA_BUS_HSS,
+};
+
+/* crystal frequency to HSIO bus frequency multiplier (HSS) */
+static unsigned char hss_mult[4] = { 8, 12, 16, 24 };
+
+/* crystal frequency to static memory controller multiplier (SMCFS) */
+static unsigned int smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
+static unsigned int df_clkdiv[4] = { 1, 2, 4, 1 };
+
+static const char * const get_freq_khz[] = {
+ "core", "ring_osc_60mhz", "run", "cpll", "system_bus"
+};
+
+/*
+ * Get the clock frequency as reflected by ACSR and the turbo flag.
+ * We assume these values have been applied via a fcs.
+ * If info is not 0 we also display the current settings.
+ */
+unsigned int pxa3xx_get_clk_frequency_khz(int info)
+{
+ struct clk *clk;
+ unsigned long clks[5];
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ clk = clk_get(NULL, get_freq_khz[i]);
+ if (IS_ERR(clk)) {
+ clks[i] = 0;
+ } else {
+ clks[i] = clk_get_rate(clk);
+ clk_put(clk);
+ }
+ }
+ if (info) {
+ pr_info("RO Mode clock: %ld.%02ldMHz\n",
+ clks[1] / 1000000, (clks[0] % 1000000) / 10000);
+ pr_info("Run Mode clock: %ld.%02ldMHz\n",
+ clks[2] / 1000000, (clks[1] % 1000000) / 10000);
+ pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
+ clks[3] / 1000000, (clks[2] % 1000000) / 10000);
+ pr_info("System bus clock: %ld.%02ldMHz\n",
+ clks[4] / 1000000, (clks[4] % 1000000) / 10000);
+ }
+ return (unsigned int)clks[0];
+}
+
+static unsigned long clk_pxa3xx_ac97_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long ac97_div, rate;
+
+ ac97_div = AC97_DIV;
+
+ /* This may loose precision for some rates but won't for the
+ * standard 24.576MHz.
+ */
+ rate = parent_rate / 2;
+ rate /= ((ac97_div >> 12) & 0x7fff);
+ rate *= (ac97_div & 0xfff);
+
+ return rate;
+}
+PARENTS(clk_pxa3xx_ac97) = { "spll_624mhz" };
+RATE_RO_OPS(clk_pxa3xx_ac97, "ac97");
+
+static unsigned long clk_pxa3xx_smemc_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = ACSR;
+ unsigned long memclkcfg = __raw_readl(MEMCLKCFG);
+
+ return (parent_rate / 48) * smcfs_mult[(acsr >> 23) & 0x7] /
+ df_clkdiv[(memclkcfg >> 16) & 0x3];
+}
+PARENTS(clk_pxa3xx_smemc) = { "spll_624mhz" };
+RATE_RO_OPS(clk_pxa3xx_smemc, "smemc");
+
+static bool pxa3xx_is_ring_osc_forced(void)
+{
+ unsigned long acsr = ACSR;
+
+ return acsr & ACCR_D0CS;
+}
+
+PARENTS(pxa3xx_pbus) = { "ring_osc_60mhz", "spll_624mhz" };
+PARENTS(pxa3xx_32Khz_bus) = { "osc_32_768khz", "osc_32_768khz" };
+PARENTS(pxa3xx_13MHz_bus) = { "osc_13mhz", "osc_13mhz" };
+PARENTS(pxa3xx_ac97_bus) = { "ring_osc_60mhz", "ac97" };
+PARENTS(pxa3xx_sbus) = { "ring_osc_60mhz", "system_bus" };
+PARENTS(pxa3xx_smemcbus) = { "ring_osc_60mhz", "smemc" };
+
+#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? &CKENA : &CKENB)
+#define PXA3XX_CKEN(dev_id, con_id, parents, mult_lp, div_lp, mult_hp, \
+ div_hp, bit, is_lp, flags) \
+ PXA_CKEN(dev_id, con_id, bit, parents, mult_lp, div_lp, \
+ mult_hp, div_hp, is_lp, CKEN_AB(bit), \
+ (CKEN_ ## bit % 32), flags)
+#define PXA3XX_PBUS_CKEN(dev_id, con_id, bit, mult_lp, div_lp, \
+ mult_hp, div_hp, delay) \
+ PXA3XX_CKEN(dev_id, con_id, pxa3xx_pbus_parents, mult_lp, \
+ div_lp, mult_hp, div_hp, bit, pxa3xx_is_ring_osc_forced, 0)
+#define PXA3XX_CKEN_1RATE(dev_id, con_id, bit, parents) \
+ PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
+ CKEN_AB(bit), (CKEN_ ## bit % 32), 0)
+
+static struct desc_clk_cken pxa3xx_clocks[] __initdata = {
+ PXA3XX_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 1, 4, 1, 42, 1),
+ PXA3XX_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 1, 4, 1, 42, 1),
+ PXA3XX_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 1, 4, 1, 42, 1),
+ PXA3XX_PBUS_CKEN("pxa2xx-i2c.0", NULL, I2C, 2, 5, 1, 19, 0),
+ PXA3XX_PBUS_CKEN("pxa27x-udc", NULL, UDC, 1, 4, 1, 13, 5),
+ PXA3XX_PBUS_CKEN("pxa27x-ohci", NULL, USBH, 1, 4, 1, 13, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-u2d", NULL, USB2, 1, 4, 1, 13, 0),
+ PXA3XX_PBUS_CKEN("pxa27x-pwm.0", NULL, PWM0, 1, 6, 1, 48, 0),
+ PXA3XX_PBUS_CKEN("pxa27x-pwm.1", NULL, PWM1, 1, 6, 1, 48, 0),
+ PXA3XX_PBUS_CKEN("pxa2xx-mci.0", NULL, MMC1, 1, 4, 1, 24, 0),
+ PXA3XX_PBUS_CKEN("pxa2xx-mci.1", NULL, MMC2, 1, 4, 1, 24, 0),
+ PXA3XX_PBUS_CKEN("pxa2xx-mci.2", NULL, MMC3, 1, 4, 1, 24, 0),
+
+ PXA3XX_CKEN_1RATE("pxa27x-keypad", NULL, KEYPAD,
+ pxa3xx_32Khz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.0", NULL, SSP1, pxa3xx_13MHz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.1", NULL, SSP2, pxa3xx_13MHz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.2", NULL, SSP3, pxa3xx_13MHz_bus_parents),
+ PXA3XX_CKEN_1RATE("pxa3xx-ssp.3", NULL, SSP4, pxa3xx_13MHz_bus_parents),
+
+ PXA3XX_CKEN(NULL, "AC97CLK", pxa3xx_ac97_bus_parents, 1, 4, 1, 1, AC97,
+ pxa3xx_is_ring_osc_forced, 0),
+ PXA3XX_CKEN(NULL, "CAMCLK", pxa3xx_sbus_parents, 1, 2, 1, 1, CAMERA,
+ pxa3xx_is_ring_osc_forced, 0),
+ PXA3XX_CKEN("pxa2xx-fb", NULL, pxa3xx_sbus_parents, 1, 1, 1, 1, LCD,
+ pxa3xx_is_ring_osc_forced, 0),
+ PXA3XX_CKEN("pxa2xx-pcmcia", NULL, pxa3xx_smemcbus_parents, 1, 4,
+ 1, 1, SMC, pxa3xx_is_ring_osc_forced, CLK_IGNORE_UNUSED),
+};
+
+static struct desc_clk_cken pxa300_310_clocks[] __initdata = {
+
+ PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA300_GCU, 1, 1, 1, 1, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 4, 0),
+ PXA3XX_CKEN_1RATE("pxa3xx-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
+};
+
+static struct desc_clk_cken pxa320_clocks[] __initdata = {
+ PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 6, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA320_GCU, 1, 1, 1, 1, 0),
+ PXA3XX_CKEN_1RATE("pxa3xx-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
+};
+
+static struct desc_clk_cken pxa93x_clocks[] __initdata = {
+
+ PXA3XX_PBUS_CKEN("pxa3xx-gcu", NULL, PXA300_GCU, 1, 1, 1, 1, 0),
+ PXA3XX_PBUS_CKEN("pxa3xx-nand", NULL, NAND, 1, 2, 1, 4, 0),
+ PXA3XX_CKEN_1RATE("pxa93x-gpio", NULL, GPIO, pxa3xx_13MHz_bus_parents),
+};
+
+static unsigned long clk_pxa3xx_system_bus_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = ACSR;
+ unsigned int hss = (acsr >> 14) & 0x3;
+
+ if (pxa3xx_is_ring_osc_forced())
+ return parent_rate;
+ return parent_rate / 48 * hss_mult[hss];
+}
+
+static u8 clk_pxa3xx_system_bus_get_parent(struct clk_hw *hw)
+{
+ if (pxa3xx_is_ring_osc_forced())
+ return PXA_BUS_60Mhz;
+ else
+ return PXA_BUS_HSS;
+}
+
+PARENTS(clk_pxa3xx_system_bus) = { "ring_osc_60mhz", "spll_624mhz" };
+MUX_RO_RATE_RO_OPS(clk_pxa3xx_system_bus, "system_bus");
+
+static unsigned long clk_pxa3xx_core_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate;
+}
+
+static u8 clk_pxa3xx_core_get_parent(struct clk_hw *hw)
+{
+ unsigned long xclkcfg;
+ unsigned int t;
+
+ if (pxa3xx_is_ring_osc_forced())
+ return PXA_CORE_60Mhz;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ if (t)
+ return PXA_CORE_TURBO;
+ return PXA_CORE_RUN;
+}
+PARENTS(clk_pxa3xx_core) = { "ring_osc_60mhz", "run", "cpll" };
+MUX_RO_RATE_RO_OPS(clk_pxa3xx_core, "core");
+
+static unsigned long clk_pxa3xx_run_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = ACSR;
+ unsigned int xn = (acsr & ACCR_XN_MASK) >> 8;
+ unsigned int t, xclkcfg;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ return t ? (parent_rate / xn) * 2 : parent_rate;
+}
+PARENTS(clk_pxa3xx_run) = { "cpll" };
+RATE_RO_OPS(clk_pxa3xx_run, "run");
+
+static unsigned long clk_pxa3xx_cpll_get_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long acsr = ACSR;
+ unsigned int xn = (acsr & ACCR_XN_MASK) >> 8;
+ unsigned int xl = acsr & ACCR_XL_MASK;
+ unsigned int t, xclkcfg;
+
+ /* Read XCLKCFG register turbo bit */
+ __asm__ __volatile__("mrc\tp14, 0, %0, c6, c0, 0" : "=r"(xclkcfg));
+ t = xclkcfg & 0x1;
+
+ pr_info("RJK: parent_rate=%lu, xl=%u, xn=%u\n", parent_rate, xl, xn);
+ return t ? parent_rate * xl * xn : parent_rate * xl;
+}
+PARENTS(clk_pxa3xx_cpll) = { "osc_13mhz" };
+RATE_RO_OPS(clk_pxa3xx_cpll, "cpll");
+
+static void __init pxa3xx_register_core(void)
+{
+ clk_register_clk_pxa3xx_cpll();
+ clk_register_clk_pxa3xx_run();
+
+ clkdev_pxa_register(CLK_CORE, "core", NULL,
+ clk_register_clk_pxa3xx_core());
+}
+
+static void __init pxa3xx_register_plls(void)
+{
+ clk_register_fixed_rate(NULL, "osc_13mhz", NULL,
+ CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+ 13 * MHz);
+ clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
+ CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+ 32768);
+ clk_register_fixed_rate(NULL, "ring_osc_120mhz", NULL,
+ CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
+ 120 * MHz);
+ clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
+ clk_register_fixed_factor(NULL, "spll_624mhz", "osc_13mhz", 0, 48, 1);
+ clk_register_fixed_factor(NULL, "ring_osc_60mhz", "ring_osc_120mhz",
+ 0, 1, 2);
+}
+
+#define DUMMY_CLK(_con_id, _dev_id, _parent) \
+ { .con_id = _con_id, .dev_id = _dev_id, .parent = _parent }
+struct dummy_clk {
+ const char *con_id;
+ const char *dev_id;
+ const char *parent;
+};
+static struct dummy_clk dummy_clks[] __initdata = {
+ DUMMY_CLK(NULL, "pxa93x-gpio", "osc_13mhz"),
+ DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
+ DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
+ DUMMY_CLK(NULL, "pxa3xx-pwri2c.1", "osc_13mhz"),
+};
+
+static void __init pxa3xx_dummy_clocks_init(void)
+{
+ struct clk *clk;
+ struct dummy_clk *d;
+ const char *name;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dummy_clks); i++) {
+ d = &dummy_clks[i];
+ name = d->dev_id ? d->dev_id : d->con_id;
+ clk = clk_register_fixed_factor(NULL, name, d->parent, 0, 1, 1);
+ clk_register_clkdev(clk, d->con_id, d->dev_id);
+ }
+}
+
+static void __init pxa3xx_base_clocks_init(void)
+{
+ pxa3xx_register_plls();
+ pxa3xx_register_core();
+ clk_register_clk_pxa3xx_system_bus();
+ clk_register_clk_pxa3xx_ac97();
+ clk_register_clk_pxa3xx_smemc();
+ clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0,
+ (void __iomem *)&OSCC, 11, 0, NULL);
+}
+
+int __init pxa3xx_clocks_init(void)
+{
+ int ret;
+
+ pxa3xx_base_clocks_init();
+ pxa3xx_dummy_clocks_init();
+ ret = clk_pxa_cken_init(pxa3xx_clocks, ARRAY_SIZE(pxa3xx_clocks));
+ if (ret)
+ return ret;
+ if (cpu_is_pxa320())
+ return clk_pxa_cken_init(pxa320_clocks,
+ ARRAY_SIZE(pxa320_clocks));
+ if (cpu_is_pxa300() || cpu_is_pxa310())
+ return clk_pxa_cken_init(pxa300_310_clocks,
+ ARRAY_SIZE(pxa300_310_clocks));
+ return clk_pxa_cken_init(pxa93x_clocks, ARRAY_SIZE(pxa93x_clocks));
+}
+
+static void __init pxa3xx_dt_clocks_init(struct device_node *np)
+{
+ pxa3xx_clocks_init();
+ clk_pxa_dt_common_init(np);
+}
+CLK_OF_DECLARE(pxa_clks, "marvell,pxa300-clocks", pxa3xx_dt_clocks_init);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 1107351ed34682..0d7ab52b7ab007 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -29,6 +29,15 @@ config IPQ_GCC_806X
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, SD/eMMC, etc.
+config IPQ_LCC_806X
+ tristate "IPQ806x LPASS Clock Controller"
+ select IPQ_GCC_806X
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the LPASS clock controller on ipq806x devices.
+ Say Y if you want to use audio devices such as i2s, pcm,
+ S/PDIF, etc.
+
config MSM_GCC_8660
tristate "MSM8660 Global Clock Controller"
depends on COMMON_CLK_QCOM
@@ -45,6 +54,15 @@ config MSM_GCC_8960
Say Y if you want to use peripheral devices such as UART, SPI,
i2c, USB, SD/eMMC, SATA, PCIe, etc.
+config MSM_LCC_8960
+ tristate "APQ8064/MSM8960 LPASS Clock Controller"
+ select MSM_GCC_8960
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the LPASS clock controller on apq8064/msm8960 devices.
+ Say Y if you want to use audio devices such as i2s, pcm,
+ SLIMBus, etc.
+
config MSM_MMCC_8960
tristate "MSM8960 Multimedia Clock Controller"
select MSM_GCC_8960
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 783cfb24faa41c..61782646959534 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -6,13 +6,17 @@ clk-qcom-y += clk-pll.o
clk-qcom-y += clk-rcg.o
clk-qcom-y += clk-rcg2.o
clk-qcom-y += clk-branch.o
+clk-qcom-y += clk-regmap-divider.o
+clk-qcom-y += clk-regmap-mux.o
clk-qcom-y += reset.o
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
+obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
+obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 60873a7f45d94b..b4325f65a1bf6f 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -141,6 +141,7 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
static long
clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_pll *pll = to_clk_pll(hw);
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index 0b93972c8807f1..0039bd7d396537 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -368,6 +368,7 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
static long _freq_tbl_determine_rate(struct clk_hw *hw,
const struct freq_tbl *f, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
unsigned long clk_flags;
@@ -397,22 +398,27 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
}
static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
- return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+ return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+ max_rate, p_rate, p);
}
static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
- return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+ return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+ max_rate, p_rate, p);
}
static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 08b8b3729f539e..742acfa18d6379 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -208,6 +208,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
}
static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -361,6 +362,8 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
}
static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -412,6 +415,7 @@ const struct clk_ops clk_edp_pixel_ops = {
EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -476,6 +480,8 @@ static const struct frac_entry frac_table_pixel[] = {
};
static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c
new file mode 100644
index 00000000000000..53484912301eee
--- /dev/null
+++ b/drivers/clk/qcom/clk-regmap-divider.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "clk-regmap-divider.h"
+
+static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw)
+{
+ return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr);
+}
+
+static long div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_regmap_div *divider = to_clk_regmap_div(hw);
+
+ return divider_round_rate(hw, rate, prate, NULL, divider->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_regmap_div *divider = to_clk_regmap_div(hw);
+ struct clk_regmap *clkr = ÷r->clkr;
+ u32 div;
+
+ div = divider_get_val(rate, parent_rate, NULL, divider->width,
+ CLK_DIVIDER_ROUND_CLOSEST);
+
+ return regmap_update_bits(clkr->regmap, divider->reg,
+ (BIT(divider->width) - 1) << divider->shift,
+ div << divider->shift);
+}
+
+static unsigned long div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_regmap_div *divider = to_clk_regmap_div(hw);
+ struct clk_regmap *clkr = ÷r->clkr;
+ u32 div;
+
+ regmap_read(clkr->regmap, divider->reg, &div);
+ div >>= divider->shift;
+ div &= BIT(divider->width) - 1;
+
+ return divider_recalc_rate(hw, parent_rate, div, NULL,
+ CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+const struct clk_ops clk_regmap_div_ops = {
+ .round_rate = div_round_rate,
+ .set_rate = div_set_rate,
+ .recalc_rate = div_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_div_ops);
diff --git a/drivers/clk/qcom/clk-regmap-divider.h b/drivers/clk/qcom/clk-regmap-divider.h
new file mode 100644
index 00000000000000..fc4492e3a82731
--- /dev/null
+++ b/drivers/clk/qcom/clk-regmap-divider.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QCOM_CLK_REGMAP_DIVIDER_H__
+#define __QCOM_CLK_REGMAP_DIVIDER_H__
+
+#include
+#include "clk-regmap.h"
+
+struct clk_regmap_div {
+ u32 reg;
+ u32 shift;
+ u32 width;
+ struct clk_regmap clkr;
+};
+
+extern const struct clk_ops clk_regmap_div_ops;
+
+#endif
diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c
new file mode 100644
index 00000000000000..cae3071f384c81
--- /dev/null
+++ b/drivers/clk/qcom/clk-regmap-mux.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "clk-regmap-mux.h"
+
+static inline struct clk_regmap_mux *to_clk_regmap_mux(struct clk_hw *hw)
+{
+ return container_of(to_clk_regmap(hw), struct clk_regmap_mux, clkr);
+}
+
+static u8 mux_get_parent(struct clk_hw *hw)
+{
+ struct clk_regmap_mux *mux = to_clk_regmap_mux(hw);
+ struct clk_regmap *clkr = to_clk_regmap(hw);
+ unsigned int mask = GENMASK(mux->width - 1, 0);
+ unsigned int val;
+
+ regmap_read(clkr->regmap, mux->reg, &val);
+
+ val >>= mux->shift;
+ val &= mask;
+
+ return val;
+}
+
+static int mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_regmap_mux *mux = to_clk_regmap_mux(hw);
+ struct clk_regmap *clkr = to_clk_regmap(hw);
+ unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
+ unsigned int val;
+
+ val = index;
+ val <<= mux->shift;
+
+ return regmap_update_bits(clkr->regmap, mux->reg, mask, val);
+}
+
+const struct clk_ops clk_regmap_mux_closest_ops = {
+ .get_parent = mux_get_parent,
+ .set_parent = mux_set_parent,
+ .determine_rate = __clk_mux_determine_rate_closest,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_mux_closest_ops);
diff --git a/drivers/clk/qcom/clk-regmap-mux.h b/drivers/clk/qcom/clk-regmap-mux.h
new file mode 100644
index 00000000000000..5cec76154fdae4
--- /dev/null
+++ b/drivers/clk/qcom/clk-regmap-mux.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QCOM_CLK_REGMAP_MUX_H__
+#define __QCOM_CLK_REGMAP_MUX_H__
+
+#include
+#include "clk-regmap.h"
+
+struct clk_regmap_mux {
+ u32 reg;
+ u32 shift;
+ u32 width;
+ struct clk_regmap clkr;
+};
+
+extern const struct clk_ops clk_regmap_mux_closest_ops;
+
+#endif
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index afed5eb0691e10..cbdc31dea7f431 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -75,6 +75,17 @@ static struct clk_pll pll3 = {
},
};
+static struct clk_regmap pll4_vote = {
+ .enable_reg = 0x34c0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pll4_vote",
+ .parent_names = (const char *[]){ "pll4" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
static struct clk_pll pll8 = {
.l_reg = 0x3144,
.m_reg = 0x3148,
@@ -2163,6 +2174,7 @@ static struct clk_regmap *gcc_ipq806x_clks[] = {
[PLL0] = &pll0.clkr,
[PLL0_VOTE] = &pll0_vote,
[PLL3] = &pll3.clkr,
+ [PLL4_VOTE] = &pll4_vote,
[PLL8] = &pll8.clkr,
[PLL8_VOTE] = &pll8_vote,
[PLL14] = &pll14.clkr,
diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c
new file mode 100644
index 00000000000000..121ffde25dc3d6
--- /dev/null
+++ b/drivers/clk/qcom/lcc-ipq806x.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+
+static struct clk_pll pll4 = {
+ .l_reg = 0x4,
+ .m_reg = 0x8,
+ .n_reg = 0xc,
+ .config_reg = 0x14,
+ .mode_reg = 0x0,
+ .status_reg = 0x18,
+ .status_bit = 16,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pll4",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static const struct pll_config pll4_config = {
+ .l = 0xf,
+ .m = 0x91,
+ .n = 0xc7,
+ .vco_val = 0x0,
+ .vco_mask = BIT(17) | BIT(16),
+ .pre_div_val = 0x0,
+ .pre_div_mask = BIT(19),
+ .post_div_val = 0x0,
+ .post_div_mask = BIT(21) | BIT(20),
+ .mn_ena_mask = BIT(22),
+ .main_output_mask = BIT(23),
+};
+
+#define P_PXO 0
+#define P_PLL4 1
+
+static const u8 lcc_pxo_pll4_map[] = {
+ [P_PXO] = 0,
+ [P_PLL4] = 2,
+};
+
+static const char *lcc_pxo_pll4[] = {
+ "pxo",
+ "pll4_vote",
+};
+
+static struct freq_tbl clk_tbl_aif_mi2s[] = {
+ { 1024000, P_PLL4, 4, 1, 96 },
+ { 1411200, P_PLL4, 4, 2, 139 },
+ { 1536000, P_PLL4, 4, 1, 64 },
+ { 2048000, P_PLL4, 4, 1, 48 },
+ { 2116800, P_PLL4, 4, 2, 93 },
+ { 2304000, P_PLL4, 4, 2, 85 },
+ { 2822400, P_PLL4, 4, 6, 209 },
+ { 3072000, P_PLL4, 4, 1, 32 },
+ { 3175200, P_PLL4, 4, 1, 31 },
+ { 4096000, P_PLL4, 4, 1, 24 },
+ { 4233600, P_PLL4, 4, 9, 209 },
+ { 4608000, P_PLL4, 4, 3, 64 },
+ { 5644800, P_PLL4, 4, 12, 209 },
+ { 6144000, P_PLL4, 4, 1, 16 },
+ { 6350400, P_PLL4, 4, 2, 31 },
+ { 8192000, P_PLL4, 4, 1, 12 },
+ { 8467200, P_PLL4, 4, 18, 209 },
+ { 9216000, P_PLL4, 4, 3, 32 },
+ { 11289600, P_PLL4, 4, 24, 209 },
+ { 12288000, P_PLL4, 4, 1, 8 },
+ { 12700800, P_PLL4, 4, 27, 209 },
+ { 13824000, P_PLL4, 4, 9, 64 },
+ { 16384000, P_PLL4, 4, 1, 6 },
+ { 16934400, P_PLL4, 4, 41, 238 },
+ { 18432000, P_PLL4, 4, 3, 16 },
+ { 22579200, P_PLL4, 2, 24, 209 },
+ { 24576000, P_PLL4, 4, 1, 4 },
+ { 27648000, P_PLL4, 4, 9, 32 },
+ { 33868800, P_PLL4, 4, 41, 119 },
+ { 36864000, P_PLL4, 4, 3, 8 },
+ { 45158400, P_PLL4, 1, 24, 209 },
+ { 49152000, P_PLL4, 4, 1, 2 },
+ { 50803200, P_PLL4, 1, 27, 209 },
+ { }
+};
+
+static struct clk_rcg mi2s_osr_src = {
+ .ns_reg = 0x48,
+ .md_reg = 0x4c,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 24,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_aif_mi2s,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_osr_src",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static const char *lcc_mi2s_parents[] = {
+ "mi2s_osr_src",
+};
+
+static struct clk_branch mi2s_osr_clk = {
+ .halt_reg = 0x50,
+ .halt_bit = 1,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_osr_clk",
+ .parent_names = lcc_mi2s_parents,
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_regmap_div mi2s_div_clk = {
+ .reg = 0x48,
+ .shift = 10,
+ .width = 4,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_div_clk",
+ .parent_names = lcc_mi2s_parents,
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ops,
+ },
+ },
+};
+
+static struct clk_branch mi2s_bit_div_clk = {
+ .halt_reg = 0x50,
+ .halt_bit = 0,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_bit_div_clk",
+ .parent_names = (const char *[]){ "mi2s_div_clk" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+
+static struct clk_regmap_mux mi2s_bit_clk = {
+ .reg = 0x48,
+ .shift = 14,
+ .width = 1,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_bit_clk",
+ .parent_names = (const char *[]){
+ "mi2s_bit_div_clk",
+ "mi2s_codec_clk",
+ },
+ .num_parents = 2,
+ .ops = &clk_regmap_mux_closest_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct freq_tbl clk_tbl_pcm[] = {
+ { 64000, P_PLL4, 4, 1, 1536 },
+ { 128000, P_PLL4, 4, 1, 768 },
+ { 256000, P_PLL4, 4, 1, 384 },
+ { 512000, P_PLL4, 4, 1, 192 },
+ { 1024000, P_PLL4, 4, 1, 96 },
+ { 2048000, P_PLL4, 4, 1, 48 },
+ { },
+};
+
+static struct clk_rcg pcm_src = {
+ .ns_reg = 0x54,
+ .md_reg = 0x58,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_pcm,
+ .clkr = {
+ .enable_reg = 0x54,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcm_src",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch pcm_clk_out = {
+ .halt_reg = 0x5c,
+ .halt_bit = 0,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x54,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcm_clk_out",
+ .parent_names = (const char *[]){ "pcm_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_regmap_mux pcm_clk = {
+ .reg = 0x54,
+ .shift = 10,
+ .width = 1,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "pcm_clk",
+ .parent_names = (const char *[]){
+ "pcm_clk_out",
+ "pcm_codec_clk",
+ },
+ .num_parents = 2,
+ .ops = &clk_regmap_mux_closest_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct freq_tbl clk_tbl_aif_osr[] = {
+ { 22050, P_PLL4, 1, 147, 20480 },
+ { 32000, P_PLL4, 1, 1, 96 },
+ { 44100, P_PLL4, 1, 147, 10240 },
+ { 48000, P_PLL4, 1, 1, 64 },
+ { 88200, P_PLL4, 1, 147, 5120 },
+ { 96000, P_PLL4, 1, 1, 32 },
+ { 176400, P_PLL4, 1, 147, 2560 },
+ { 192000, P_PLL4, 1, 1, 16 },
+ { },
+};
+
+static struct clk_rcg spdif_src = {
+ .ns_reg = 0xcc,
+ .md_reg = 0xd0,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_aif_osr,
+ .clkr = {
+ .enable_reg = 0xcc,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "spdif_src",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static const char *lcc_spdif_parents[] = {
+ "spdif_src",
+};
+
+static struct clk_branch spdif_clk = {
+ .halt_reg = 0xd4,
+ .halt_bit = 1,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0xcc,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "spdif_clk",
+ .parent_names = lcc_spdif_parents,
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct freq_tbl clk_tbl_ahbix[] = {
+ { 131072, P_PLL4, 1, 1, 3 },
+ { },
+};
+
+static struct clk_rcg ahbix_clk = {
+ .ns_reg = 0x38,
+ .md_reg = 0x3c,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 24,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_ahbix,
+ .clkr = {
+ .enable_reg = 0x38,
+ .enable_mask = BIT(10), /* toggle the gfmux to select mn/pxo */
+ .hw.init = &(struct clk_init_data){
+ .name = "ahbix",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_regmap *lcc_ipq806x_clks[] = {
+ [PLL4] = &pll4.clkr,
+ [MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
+ [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
+ [MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
+ [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
+ [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
+ [PCM_SRC] = &pcm_src.clkr,
+ [PCM_CLK_OUT] = &pcm_clk_out.clkr,
+ [PCM_CLK] = &pcm_clk.clkr,
+ [SPDIF_SRC] = &spdif_src.clkr,
+ [SPDIF_CLK] = &spdif_clk.clkr,
+ [AHBIX_CLK] = &ahbix_clk.clkr,
+};
+
+static const struct regmap_config lcc_ipq806x_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xfc,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc lcc_ipq806x_desc = {
+ .config = &lcc_ipq806x_regmap_config,
+ .clks = lcc_ipq806x_clks,
+ .num_clks = ARRAY_SIZE(lcc_ipq806x_clks),
+};
+
+static const struct of_device_id lcc_ipq806x_match_table[] = {
+ { .compatible = "qcom,lcc-ipq8064" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lcc_ipq806x_match_table);
+
+static int lcc_ipq806x_probe(struct platform_device *pdev)
+{
+ u32 val;
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &lcc_ipq806x_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* Configure the rate of PLL4 if the bootloader hasn't already */
+ val = regmap_read(regmap, 0x0, &val);
+ if (!val)
+ clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
+ /* Enable PLL4 source on the LPASS Primary PLL Mux */
+ regmap_write(regmap, 0xc4, 0x1);
+
+ return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
+}
+
+static int lcc_ipq806x_remove(struct platform_device *pdev)
+{
+ qcom_cc_remove(pdev);
+ return 0;
+}
+
+static struct platform_driver lcc_ipq806x_driver = {
+ .probe = lcc_ipq806x_probe,
+ .remove = lcc_ipq806x_remove,
+ .driver = {
+ .name = "lcc-ipq806x",
+ .owner = THIS_MODULE,
+ .of_match_table = lcc_ipq806x_match_table,
+ },
+};
+module_platform_driver(lcc_ipq806x_driver);
+
+MODULE_DESCRIPTION("QCOM LCC IPQ806x Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:lcc-ipq806x");
diff --git a/drivers/clk/qcom/lcc-msm8960.c b/drivers/clk/qcom/lcc-msm8960.c
new file mode 100644
index 00000000000000..a75a408cfccddf
--- /dev/null
+++ b/drivers/clk/qcom/lcc-msm8960.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+
+static struct clk_pll pll4 = {
+ .l_reg = 0x4,
+ .m_reg = 0x8,
+ .n_reg = 0xc,
+ .config_reg = 0x14,
+ .mode_reg = 0x0,
+ .status_reg = 0x18,
+ .status_bit = 16,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pll4",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+#define P_PXO 0
+#define P_PLL4 1
+
+static const u8 lcc_pxo_pll4_map[] = {
+ [P_PXO] = 0,
+ [P_PLL4] = 2,
+};
+
+static const char *lcc_pxo_pll4[] = {
+ "pxo",
+ "pll4_vote",
+};
+
+static struct freq_tbl clk_tbl_aif_osr_492[] = {
+ { 512000, P_PLL4, 4, 1, 240 },
+ { 768000, P_PLL4, 4, 1, 160 },
+ { 1024000, P_PLL4, 4, 1, 120 },
+ { 1536000, P_PLL4, 4, 1, 80 },
+ { 2048000, P_PLL4, 4, 1, 60 },
+ { 3072000, P_PLL4, 4, 1, 40 },
+ { 4096000, P_PLL4, 4, 1, 30 },
+ { 6144000, P_PLL4, 4, 1, 20 },
+ { 8192000, P_PLL4, 4, 1, 15 },
+ { 12288000, P_PLL4, 4, 1, 10 },
+ { 24576000, P_PLL4, 4, 1, 5 },
+ { 27000000, P_PXO, 1, 0, 0 },
+ { }
+};
+
+static struct freq_tbl clk_tbl_aif_osr_393[] = {
+ { 512000, P_PLL4, 4, 1, 192 },
+ { 768000, P_PLL4, 4, 1, 128 },
+ { 1024000, P_PLL4, 4, 1, 96 },
+ { 1536000, P_PLL4, 4, 1, 64 },
+ { 2048000, P_PLL4, 4, 1, 48 },
+ { 3072000, P_PLL4, 4, 1, 32 },
+ { 4096000, P_PLL4, 4, 1, 24 },
+ { 6144000, P_PLL4, 4, 1, 16 },
+ { 8192000, P_PLL4, 4, 1, 12 },
+ { 12288000, P_PLL4, 4, 1, 8 },
+ { 24576000, P_PLL4, 4, 1, 4 },
+ { 27000000, P_PXO, 1, 0, 0 },
+ { }
+};
+
+static struct clk_rcg mi2s_osr_src = {
+ .ns_reg = 0x48,
+ .md_reg = 0x4c,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 24,
+ .m_val_shift = 8,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_aif_osr_393,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_osr_src",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static const char *lcc_mi2s_parents[] = {
+ "mi2s_osr_src",
+};
+
+static struct clk_branch mi2s_osr_clk = {
+ .halt_reg = 0x50,
+ .halt_bit = 1,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_osr_clk",
+ .parent_names = lcc_mi2s_parents,
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_regmap_div mi2s_div_clk = {
+ .reg = 0x48,
+ .shift = 10,
+ .width = 4,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_div_clk",
+ .parent_names = lcc_mi2s_parents,
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ops,
+ },
+ },
+};
+
+static struct clk_branch mi2s_bit_div_clk = {
+ .halt_reg = 0x50,
+ .halt_bit = 0,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x48,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_bit_div_clk",
+ .parent_names = (const char *[]){ "mi2s_div_clk" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_regmap_mux mi2s_bit_clk = {
+ .reg = 0x48,
+ .shift = 14,
+ .width = 1,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "mi2s_bit_clk",
+ .parent_names = (const char *[]){
+ "mi2s_bit_div_clk",
+ "mi2s_codec_clk",
+ },
+ .num_parents = 2,
+ .ops = &clk_regmap_mux_closest_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+#define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr) \
+static struct clk_rcg prefix##_osr_src = { \
+ .ns_reg = _ns, \
+ .md_reg = _md, \
+ .mn = { \
+ .mnctr_en_bit = 8, \
+ .mnctr_reset_bit = 7, \
+ .mnctr_mode_shift = 5, \
+ .n_val_shift = 24, \
+ .m_val_shift = 8, \
+ .width = 8, \
+ }, \
+ .p = { \
+ .pre_div_shift = 3, \
+ .pre_div_width = 2, \
+ }, \
+ .s = { \
+ .src_sel_shift = 0, \
+ .parent_map = lcc_pxo_pll4_map, \
+ }, \
+ .freq_tbl = clk_tbl_aif_osr_393, \
+ .clkr = { \
+ .enable_reg = _ns, \
+ .enable_mask = BIT(9), \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #prefix "_osr_src", \
+ .parent_names = lcc_pxo_pll4, \
+ .num_parents = 2, \
+ .ops = &clk_rcg_ops, \
+ .flags = CLK_SET_RATE_GATE, \
+ }, \
+ }, \
+}; \
+ \
+static const char *lcc_##prefix##_parents[] = { \
+ #prefix "_osr_src", \
+}; \
+ \
+static struct clk_branch prefix##_osr_clk = { \
+ .halt_reg = hr, \
+ .halt_bit = 1, \
+ .halt_check = BRANCH_HALT_ENABLE, \
+ .clkr = { \
+ .enable_reg = _ns, \
+ .enable_mask = BIT(21), \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #prefix "_osr_clk", \
+ .parent_names = lcc_##prefix##_parents, \
+ .num_parents = 1, \
+ .ops = &clk_branch_ops, \
+ .flags = CLK_SET_RATE_PARENT, \
+ }, \
+ }, \
+}; \
+ \
+static struct clk_regmap_div prefix##_div_clk = { \
+ .reg = _ns, \
+ .shift = 10, \
+ .width = 8, \
+ .clkr = { \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #prefix "_div_clk", \
+ .parent_names = lcc_##prefix##_parents, \
+ .num_parents = 1, \
+ .ops = &clk_regmap_div_ops, \
+ }, \
+ }, \
+}; \
+ \
+static struct clk_branch prefix##_bit_div_clk = { \
+ .halt_reg = hr, \
+ .halt_bit = 0, \
+ .halt_check = BRANCH_HALT_ENABLE, \
+ .clkr = { \
+ .enable_reg = _ns, \
+ .enable_mask = BIT(19), \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #prefix "_bit_div_clk", \
+ .parent_names = (const char *[]){ \
+ #prefix "_div_clk" \
+ }, \
+ .num_parents = 1, \
+ .ops = &clk_branch_ops, \
+ .flags = CLK_SET_RATE_PARENT, \
+ }, \
+ }, \
+}; \
+ \
+static struct clk_regmap_mux prefix##_bit_clk = { \
+ .reg = _ns, \
+ .shift = 18, \
+ .width = 1, \
+ .clkr = { \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #prefix "_bit_clk", \
+ .parent_names = (const char *[]){ \
+ #prefix "_bit_div_clk", \
+ #prefix "_codec_clk", \
+ }, \
+ .num_parents = 2, \
+ .ops = &clk_regmap_mux_closest_ops, \
+ .flags = CLK_SET_RATE_PARENT, \
+ }, \
+ }, \
+}
+
+CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68);
+CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80);
+CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74);
+CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c);
+
+static struct freq_tbl clk_tbl_pcm_492[] = {
+ { 256000, P_PLL4, 4, 1, 480 },
+ { 512000, P_PLL4, 4, 1, 240 },
+ { 768000, P_PLL4, 4, 1, 160 },
+ { 1024000, P_PLL4, 4, 1, 120 },
+ { 1536000, P_PLL4, 4, 1, 80 },
+ { 2048000, P_PLL4, 4, 1, 60 },
+ { 3072000, P_PLL4, 4, 1, 40 },
+ { 4096000, P_PLL4, 4, 1, 30 },
+ { 6144000, P_PLL4, 4, 1, 20 },
+ { 8192000, P_PLL4, 4, 1, 15 },
+ { 12288000, P_PLL4, 4, 1, 10 },
+ { 24576000, P_PLL4, 4, 1, 5 },
+ { 27000000, P_PXO, 1, 0, 0 },
+ { }
+};
+
+static struct freq_tbl clk_tbl_pcm_393[] = {
+ { 256000, P_PLL4, 4, 1, 384 },
+ { 512000, P_PLL4, 4, 1, 192 },
+ { 768000, P_PLL4, 4, 1, 128 },
+ { 1024000, P_PLL4, 4, 1, 96 },
+ { 1536000, P_PLL4, 4, 1, 64 },
+ { 2048000, P_PLL4, 4, 1, 48 },
+ { 3072000, P_PLL4, 4, 1, 32 },
+ { 4096000, P_PLL4, 4, 1, 24 },
+ { 6144000, P_PLL4, 4, 1, 16 },
+ { 8192000, P_PLL4, 4, 1, 12 },
+ { 12288000, P_PLL4, 4, 1, 8 },
+ { 24576000, P_PLL4, 4, 1, 4 },
+ { 27000000, P_PXO, 1, 0, 0 },
+ { }
+};
+
+static struct clk_rcg pcm_src = {
+ .ns_reg = 0x54,
+ .md_reg = 0x58,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_pcm_393,
+ .clkr = {
+ .enable_reg = 0x54,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcm_src",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch pcm_clk_out = {
+ .halt_reg = 0x5c,
+ .halt_bit = 0,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0x54,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcm_clk_out",
+ .parent_names = (const char *[]){ "pcm_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_regmap_mux pcm_clk = {
+ .reg = 0x54,
+ .shift = 10,
+ .width = 1,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "pcm_clk",
+ .parent_names = (const char *[]){
+ "pcm_clk_out",
+ "pcm_codec_clk",
+ },
+ .num_parents = 2,
+ .ops = &clk_regmap_mux_closest_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg slimbus_src = {
+ .ns_reg = 0xcc,
+ .md_reg = 0xd0,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = lcc_pxo_pll4_map,
+ },
+ .freq_tbl = clk_tbl_aif_osr_393,
+ .clkr = {
+ .enable_reg = 0xcc,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "slimbus_src",
+ .parent_names = lcc_pxo_pll4,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static const char *lcc_slimbus_parents[] = {
+ "slimbus_src",
+};
+
+static struct clk_branch audio_slimbus_clk = {
+ .halt_reg = 0xd4,
+ .halt_bit = 0,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0xcc,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "audio_slimbus_clk",
+ .parent_names = lcc_slimbus_parents,
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch sps_slimbus_clk = {
+ .halt_reg = 0xd4,
+ .halt_bit = 1,
+ .halt_check = BRANCH_HALT_ENABLE,
+ .clkr = {
+ .enable_reg = 0xcc,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "sps_slimbus_clk",
+ .parent_names = lcc_slimbus_parents,
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_regmap *lcc_msm8960_clks[] = {
+ [PLL4] = &pll4.clkr,
+ [MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
+ [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
+ [MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
+ [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
+ [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
+ [PCM_SRC] = &pcm_src.clkr,
+ [PCM_CLK_OUT] = &pcm_clk_out.clkr,
+ [PCM_CLK] = &pcm_clk.clkr,
+ [SLIMBUS_SRC] = &slimbus_src.clkr,
+ [AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr,
+ [SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr,
+ [CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr,
+ [CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr,
+ [CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr,
+ [CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr,
+ [CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr,
+ [SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr,
+ [SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr,
+ [SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr,
+ [SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr,
+ [SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr,
+ [CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr,
+ [CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr,
+ [CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr,
+ [CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr,
+ [CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr,
+ [SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr,
+ [SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr,
+ [SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr,
+ [SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr,
+ [SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr,
+};
+
+static const struct regmap_config lcc_msm8960_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xfc,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc lcc_msm8960_desc = {
+ .config = &lcc_msm8960_regmap_config,
+ .clks = lcc_msm8960_clks,
+ .num_clks = ARRAY_SIZE(lcc_msm8960_clks),
+};
+
+static const struct of_device_id lcc_msm8960_match_table[] = {
+ { .compatible = "qcom,lcc-msm8960" },
+ { .compatible = "qcom,lcc-apq8064" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lcc_msm8960_match_table);
+
+static int lcc_msm8960_probe(struct platform_device *pdev)
+{
+ u32 val;
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &lcc_msm8960_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* Use the correct frequency plan depending on speed of PLL4 */
+ val = regmap_read(regmap, 0x4, &val);
+ if (val == 0x12) {
+ slimbus_src.freq_tbl = clk_tbl_aif_osr_492;
+ mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492;
+ codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
+ spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
+ codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
+ spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
+ pcm_src.freq_tbl = clk_tbl_pcm_492;
+ }
+ /* Enable PLL4 source on the LPASS Primary PLL Mux */
+ regmap_write(regmap, 0xc4, 0x1);
+
+ return qcom_cc_really_probe(pdev, &lcc_msm8960_desc, regmap);
+}
+
+static int lcc_msm8960_remove(struct platform_device *pdev)
+{
+ qcom_cc_remove(pdev);
+ return 0;
+}
+
+static struct platform_driver lcc_msm8960_driver = {
+ .probe = lcc_msm8960_probe,
+ .remove = lcc_msm8960_remove,
+ .driver = {
+ .name = "lcc-msm8960",
+ .owner = THIS_MODULE,
+ .of_match_table = lcc_msm8960_match_table,
+ },
+};
+module_platform_driver(lcc_msm8960_driver);
+
+MODULE_DESCRIPTION("QCOM LCC MSM8960 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:lcc-msm8960");
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index cbcddcc0247523..05d7a0bc059907 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -535,44 +535,44 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 8, GFLAGS),
- COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", 0,
+ COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(17), 0,
RK3288_CLKGATE_CON(1), 9, GFLAGS),
- MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, 0,
+ MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 10, GFLAGS),
- COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", 0,
+ COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(18), 0,
RK3288_CLKGATE_CON(1), 11, GFLAGS),
- MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, 0,
+ MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 12, GFLAGS),
- COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", 0,
+ COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(19), 0,
RK3288_CLKGATE_CON(1), 13, GFLAGS),
- MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, 0,
+ MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 14, GFLAGS),
- COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", 0,
+ COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(20), 0,
RK3288_CLKGATE_CON(1), 15, GFLAGS),
- MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, 0,
+ MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(2), 12, GFLAGS),
- COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", 0,
+ COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(7), 0,
RK3288_CLKGATE_CON(2), 13, GFLAGS),
- MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, 0,
+ MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
@@ -598,7 +598,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(0, "jtag", "ext_jtag", 0,
RK3288_CLKGATE_CON(4), 14, GFLAGS),
- COMPOSITE_NODIV(0, "usbphy480m_src", mux_usbphy480m_p, 0,
+ COMPOSITE_NODIV(SCLK_USBPHY480M_SRC, "usbphy480m_src", mux_usbphy480m_p, 0,
RK3288_CLKSEL_CON(13), 11, 2, MFLAGS,
RK3288_CLKGATE_CON(5), 14, GFLAGS),
COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
@@ -704,8 +704,8 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(SCLK_LCDC_PWM0, "sclk_lcdc_pwm0", "xin24m", 0, RK3288_CLKGATE_CON(13), 10, GFLAGS),
GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS),
- GATE(0, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
- GATE(0, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
+ GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
+ GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
/* sclk_gpu gates */
@@ -805,6 +805,20 @@ static int rk3288_clk_suspend(void)
rk3288_saved_cru_regs[i] =
readl_relaxed(rk3288_cru_base + reg_id);
}
+
+ /*
+ * Switch PLLs other than DPLL (for SDRAM) to slow mode to
+ * avoid crashes on resume. The Mask ROM on the system will
+ * put APLL, CPLL, and GPLL into slow mode at resume time
+ * anyway (which is why we restore them), but we might not
+ * even make it to the Mask ROM if this isn't done at suspend
+ * time.
+ *
+ * NOTE: only APLL truly matters here, but we'll do them all.
+ */
+
+ writel_relaxed(0xf3030000, rk3288_cru_base + RK3288_MODE_CON);
+
return 0;
}
@@ -866,6 +880,14 @@ static void __init rk3288_clk_init(struct device_node *np)
pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
__func__, PTR_ERR(clk));
+ /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
+ clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
+ if (IS_ERR(clk))
+ pr_warn("%s: could not register clock pclk_wdt: %ld\n",
+ __func__, PTR_ERR(clk));
+ else
+ rockchip_clk_add_lookup(clk, PCLK_WDT);
+
rockchip_clk_register_plls(rk3288_pll_clks,
ARRAY_SIZE(rk3288_pll_clks),
RK3288_GRF_SOC_STATUS1);
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index f2c2ccce49bb1a..454b02ae486a86 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -82,6 +82,26 @@ static const struct of_device_id exynos_audss_clk_of_match[] = {
{},
};
+static void exynos_audss_clk_teardown(void)
+{
+ int i;
+
+ for (i = EXYNOS_MOUT_AUDSS; i < EXYNOS_DOUT_SRP; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister_mux(clk_table[i]);
+ }
+
+ for (; i < EXYNOS_SRP_CLK; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister_divider(clk_table[i]);
+ }
+
+ for (; i < clk_data.clk_num; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister_gate(clk_table[i]);
+ }
+}
+
/* register exynos_audss clocks */
static int exynos_audss_clk_probe(struct platform_device *pdev)
{
@@ -219,10 +239,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
return 0;
unregister:
- for (i = 0; i < clk_data.clk_num; i++) {
- if (!IS_ERR(clk_table[i]))
- clk_unregister(clk_table[i]);
- }
+ exynos_audss_clk_teardown();
if (!IS_ERR(epll))
clk_disable_unprepare(epll);
@@ -232,18 +249,13 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
static int exynos_audss_clk_remove(struct platform_device *pdev)
{
- int i;
-
#ifdef CONFIG_PM_SLEEP
unregister_syscore_ops(&exynos_audss_clk_syscore_ops);
#endif
of_clk_del_provider(pdev->dev.of_node);
- for (i = 0; i < clk_data.clk_num; i++) {
- if (!IS_ERR(clk_table[i]))
- clk_unregister(clk_table[i]);
- }
+ exynos_audss_clk_teardown();
if (!IS_ERR(epll))
clk_disable_unprepare(epll);
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 6e6cca3920829b..cc4c348d8a2403 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -104,27 +104,6 @@
#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
-/* list of PLLs to be registered */
-enum exynos3250_plls {
- apll, mpll, vpll, upll,
- nr_plls
-};
-
-/* list of PLLs in DMC block to be registered */
-enum exynos3250_dmc_plls {
- bpll, epll,
- nr_dmc_plls
-};
-
-static void __iomem *reg_base;
-static void __iomem *dmc_reg_base;
-
-/*
- * Support for CMU save/restore across system suspends
- */
-#ifdef CONFIG_PM_SLEEP
-static struct samsung_clk_reg_dump *exynos3250_clk_regs;
-
static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
SRC_LEFTBUS,
DIV_LEFTBUS,
@@ -195,43 +174,6 @@ static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
PWR_CTRL2,
};
-static int exynos3250_clk_suspend(void)
-{
- samsung_clk_save(reg_base, exynos3250_clk_regs,
- ARRAY_SIZE(exynos3250_cmu_clk_regs));
- return 0;
-}
-
-static void exynos3250_clk_resume(void)
-{
- samsung_clk_restore(reg_base, exynos3250_clk_regs,
- ARRAY_SIZE(exynos3250_cmu_clk_regs));
-}
-
-static struct syscore_ops exynos3250_clk_syscore_ops = {
- .suspend = exynos3250_clk_suspend,
- .resume = exynos3250_clk_resume,
-};
-
-static void exynos3250_clk_sleep_init(void)
-{
- exynos3250_clk_regs =
- samsung_clk_alloc_reg_dump(exynos3250_cmu_clk_regs,
- ARRAY_SIZE(exynos3250_cmu_clk_regs));
- if (!exynos3250_clk_regs) {
- pr_warn("%s: Failed to allocate sleep save data\n", __func__);
- goto err;
- }
-
- register_syscore_ops(&exynos3250_clk_syscore_ops);
- return;
-err:
- kfree(exynos3250_clk_regs);
-}
-#else
-static inline void exynos3250_clk_sleep_init(void) { }
-#endif
-
/* list of all parent clock list */
PNAME(mout_vpllsrc_p) = { "fin_pll", };
@@ -782,18 +724,18 @@ static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
{ /* sentinel */ }
};
-static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = {
- [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
- APLL_LOCK, APLL_CON0, NULL),
- [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
- MPLL_LOCK, MPLL_CON0, NULL),
- [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "fin_pll",
- VPLL_LOCK, VPLL_CON0, NULL),
- [upll] = PLL(pll_35xx, CLK_FOUT_UPLL, "fout_upll", "fin_pll",
- UPLL_LOCK, UPLL_CON0, NULL),
+static struct samsung_pll_clock exynos3250_plls[] __initdata = {
+ PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, exynos3250_pll_rates),
+ PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON0, exynos3250_pll_rates),
+ PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "fin_pll",
+ VPLL_LOCK, VPLL_CON0, exynos3250_vpll_rates),
+ PLL(pll_35xx, CLK_FOUT_UPLL, "fout_upll", "fin_pll",
+ UPLL_LOCK, UPLL_CON0, exynos3250_pll_rates),
};
-static void __init exynos3_core_down_clock(void)
+static void __init exynos3_core_down_clock(void __iomem *reg_base)
{
unsigned int tmp;
@@ -814,38 +756,31 @@ static void __init exynos3_core_down_clock(void)
__raw_writel(0x0, reg_base + PWR_CTRL2);
}
+static struct samsung_cmu_info cmu_info __initdata = {
+ .pll_clks = exynos3250_plls,
+ .nr_pll_clks = ARRAY_SIZE(exynos3250_plls),
+ .mux_clks = mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(mux_clks),
+ .div_clks = div_clks,
+ .nr_div_clks = ARRAY_SIZE(div_clks),
+ .gate_clks = gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(gate_clks),
+ .fixed_factor_clks = fixed_factor_clks,
+ .nr_fixed_factor_clks = ARRAY_SIZE(fixed_factor_clks),
+ .nr_clk_ids = CLK_NR_CLKS,
+ .clk_regs = exynos3250_cmu_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(exynos3250_cmu_clk_regs),
+};
+
static void __init exynos3250_cmu_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
- reg_base = of_iomap(np, 0);
- if (!reg_base)
- panic("%s: failed to map registers\n", __func__);
-
- ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
+ ctx = samsung_cmu_register_one(np, &cmu_info);
if (!ctx)
- panic("%s: unable to allocate context.\n", __func__);
-
- samsung_clk_register_fixed_factor(ctx, fixed_factor_clks,
- ARRAY_SIZE(fixed_factor_clks));
-
- exynos3250_plls[apll].rate_table = exynos3250_pll_rates;
- exynos3250_plls[mpll].rate_table = exynos3250_pll_rates;
- exynos3250_plls[vpll].rate_table = exynos3250_vpll_rates;
- exynos3250_plls[upll].rate_table = exynos3250_pll_rates;
-
- samsung_clk_register_pll(ctx, exynos3250_plls,
- ARRAY_SIZE(exynos3250_plls), reg_base);
-
- samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
- samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
- samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
-
- exynos3_core_down_clock();
+ return;
- exynos3250_clk_sleep_init();
-
- samsung_clk_of_add_provider(np, ctx);
+ exynos3_core_down_clock(ctx->reg_base);
}
CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
@@ -872,12 +807,6 @@ CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
#define EPLL_CON2 0x111c
#define SRC_EPLL 0x1120
-/*
- * Support for CMU save/restore across system suspends
- */
-#ifdef CONFIG_PM_SLEEP
-static struct samsung_clk_reg_dump *exynos3250_dmc_clk_regs;
-
static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
BPLL_LOCK,
BPLL_CON0,
@@ -899,43 +828,6 @@ static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
SRC_EPLL,
};
-static int exynos3250_dmc_clk_suspend(void)
-{
- samsung_clk_save(dmc_reg_base, exynos3250_dmc_clk_regs,
- ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
- return 0;
-}
-
-static void exynos3250_dmc_clk_resume(void)
-{
- samsung_clk_restore(dmc_reg_base, exynos3250_dmc_clk_regs,
- ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
-}
-
-static struct syscore_ops exynos3250_dmc_clk_syscore_ops = {
- .suspend = exynos3250_dmc_clk_suspend,
- .resume = exynos3250_dmc_clk_resume,
-};
-
-static void exynos3250_dmc_clk_sleep_init(void)
-{
- exynos3250_dmc_clk_regs =
- samsung_clk_alloc_reg_dump(exynos3250_cmu_dmc_clk_regs,
- ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
- if (!exynos3250_dmc_clk_regs) {
- pr_warn("%s: Failed to allocate sleep save data\n", __func__);
- goto err;
- }
-
- register_syscore_ops(&exynos3250_dmc_clk_syscore_ops);
- return;
-err:
- kfree(exynos3250_dmc_clk_regs);
-}
-#else
-static inline void exynos3250_dmc_clk_sleep_init(void) { }
-#endif
-
PNAME(mout_epll_p) = { "fin_pll", "fout_epll", };
PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", };
PNAME(mout_mpll_mif_p) = { "fin_pll", "sclk_mpll_mif", };
@@ -977,43 +869,28 @@ static struct samsung_div_clock dmc_div_clks[] __initdata = {
DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3),
};
-static struct samsung_pll_clock exynos3250_dmc_plls[nr_dmc_plls] __initdata = {
- [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
- BPLL_LOCK, BPLL_CON0, NULL),
- [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
- EPLL_LOCK, EPLL_CON0, NULL),
+static struct samsung_pll_clock exynos3250_dmc_plls[] __initdata = {
+ PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
+ BPLL_LOCK, BPLL_CON0, exynos3250_pll_rates),
+ PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, exynos3250_epll_rates),
+};
+
+static struct samsung_cmu_info dmc_cmu_info __initdata = {
+ .pll_clks = exynos3250_dmc_plls,
+ .nr_pll_clks = ARRAY_SIZE(exynos3250_dmc_plls),
+ .mux_clks = dmc_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(dmc_mux_clks),
+ .div_clks = dmc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(dmc_div_clks),
+ .nr_clk_ids = NR_CLKS_DMC,
+ .clk_regs = exynos3250_cmu_dmc_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs),
};
static void __init exynos3250_cmu_dmc_init(struct device_node *np)
{
- struct samsung_clk_provider *ctx;
-
- dmc_reg_base = of_iomap(np, 0);
- if (!dmc_reg_base)
- panic("%s: failed to map registers\n", __func__);
-
- ctx = samsung_clk_init(np, dmc_reg_base, NR_CLKS_DMC);
- if (!ctx)
- panic("%s: unable to allocate context.\n", __func__);
-
- exynos3250_dmc_plls[bpll].rate_table = exynos3250_pll_rates;
- exynos3250_dmc_plls[epll].rate_table = exynos3250_epll_rates;
-
- pr_err("CLK registering epll bpll: %d, %d, %d, %d\n",
- exynos3250_dmc_plls[bpll].rate_table[0].rate,
- exynos3250_dmc_plls[bpll].rate_table[0].mdiv,
- exynos3250_dmc_plls[bpll].rate_table[0].pdiv,
- exynos3250_dmc_plls[bpll].rate_table[0].sdiv
- );
- samsung_clk_register_pll(ctx, exynos3250_dmc_plls,
- ARRAY_SIZE(exynos3250_dmc_plls), dmc_reg_base);
-
- samsung_clk_register_mux(ctx, dmc_mux_clks, ARRAY_SIZE(dmc_mux_clks));
- samsung_clk_register_div(ctx, dmc_div_clks, ARRAY_SIZE(dmc_div_clks));
-
- exynos3250_dmc_clk_sleep_init();
-
- samsung_clk_of_add_provider(np, ctx);
+ samsung_cmu_register_one(np, &dmc_cmu_info);
}
CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
exynos3250_cmu_dmc_init);
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 88e8c6bbd77ff8..51462e85675f7f 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -703,12 +703,12 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
/* list of divider clocks supported in all exynos4 soc's */
static struct samsung_div_clock exynos4_div_clks[] __initdata = {
- DIV(0, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
+ DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus",
CLKOUT_CMU_LEFTBUS, 8, 6),
- DIV(0, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 3),
+ DIV(CLK_DIV_GDR, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 3),
DIV(0, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3),
DIV(0, "div_clkout_rightbus", "mout_clkout_rightbus",
CLKOUT_CMU_RIGHTBUS, 8, 6),
@@ -781,10 +781,10 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
CLK_SET_RATE_PARENT, 0),
DIV(0, "div_clkout_top", "mout_clkout_top", CLKOUT_CMU_TOP, 8, 6),
- DIV(0, "div_acp", "mout_dmc_bus", DIV_DMC0, 0, 3),
+ DIV(CLK_DIV_ACP, "div_acp", "mout_dmc_bus", DIV_DMC0, 0, 3),
DIV(0, "div_acp_pclk", "div_acp", DIV_DMC0, 4, 3),
DIV(0, "div_dphy", "mout_dphy", DIV_DMC0, 8, 3),
- DIV(0, "div_dmc", "mout_dmc_bus", DIV_DMC0, 12, 3),
+ DIV(CLK_DIV_DMC, "div_dmc", "mout_dmc_bus", DIV_DMC0, 12, 3),
DIV(0, "div_dmcd", "div_dmc", DIV_DMC0, 16, 3),
DIV(0, "div_dmcp", "div_dmcd", DIV_DMC0, 20, 3),
DIV(0, "div_pwi", "mout_pwi", DIV_DMC1, 8, 4),
@@ -829,7 +829,7 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
8, 3, CLK_GET_RATE_NOCACHE, 0),
DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
- DIV(0, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
+ DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
};
diff --git a/drivers/clk/samsung/clk-exynos4415.c b/drivers/clk/samsung/clk-exynos4415.c
index 2123fc251e0f69..6c78b09c829f91 100644
--- a/drivers/clk/samsung/clk-exynos4415.c
+++ b/drivers/clk/samsung/clk-exynos4415.c
@@ -113,19 +113,6 @@
#define DIV_CPU0 0x14500
#define DIV_CPU1 0x14504
-enum exynos4415_plls {
- apll, epll, g3d_pll, isp_pll, disp_pll,
- nr_plls,
-};
-
-static struct samsung_clk_provider *exynos4415_ctx;
-
-/*
- * Support for CMU save/restore across system suspends
- */
-#ifdef CONFIG_PM_SLEEP
-static struct samsung_clk_reg_dump *exynos4415_clk_regs;
-
static unsigned long exynos4415_cmu_clk_regs[] __initdata = {
SRC_LEFTBUS,
DIV_LEFTBUS,
@@ -219,41 +206,6 @@ static unsigned long exynos4415_cmu_clk_regs[] __initdata = {
DIV_CPU1,
};
-static int exynos4415_clk_suspend(void)
-{
- samsung_clk_save(exynos4415_ctx->reg_base, exynos4415_clk_regs,
- ARRAY_SIZE(exynos4415_cmu_clk_regs));
-
- return 0;
-}
-
-static void exynos4415_clk_resume(void)
-{
- samsung_clk_restore(exynos4415_ctx->reg_base, exynos4415_clk_regs,
- ARRAY_SIZE(exynos4415_cmu_clk_regs));
-}
-
-static struct syscore_ops exynos4415_clk_syscore_ops = {
- .suspend = exynos4415_clk_suspend,
- .resume = exynos4415_clk_resume,
-};
-
-static void exynos4415_clk_sleep_init(void)
-{
- exynos4415_clk_regs =
- samsung_clk_alloc_reg_dump(exynos4415_cmu_clk_regs,
- ARRAY_SIZE(exynos4415_cmu_clk_regs));
- if (!exynos4415_clk_regs) {
- pr_warn("%s: Failed to allocate sleep save data\n", __func__);
- return;
- }
-
- register_syscore_ops(&exynos4415_clk_syscore_ops);
-}
-#else
-static inline void exynos4415_clk_sleep_init(void) { }
-#endif
-
/* list of all parent clock list */
PNAME(mout_g3d_pllsrc_p) = { "fin_pll", };
@@ -959,56 +911,40 @@ static struct samsung_pll_rate_table exynos4415_epll_rates[] = {
{ /* sentinel */ }
};
-static struct samsung_pll_clock exynos4415_plls[nr_plls] __initdata = {
- [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
- APLL_LOCK, APLL_CON0, NULL),
- [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
- EPLL_LOCK, EPLL_CON0, NULL),
- [g3d_pll] = PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll",
- "mout_g3d_pllsrc", G3D_PLL_LOCK, G3D_PLL_CON0, NULL),
- [isp_pll] = PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "fin_pll",
- ISP_PLL_LOCK, ISP_PLL_CON0, NULL),
- [disp_pll] = PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll",
- "fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, NULL),
+static struct samsung_pll_clock exynos4415_plls[] __initdata = {
+ PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, exynos4415_pll_rates),
+ PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, exynos4415_epll_rates),
+ PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll", "mout_g3d_pllsrc",
+ G3D_PLL_LOCK, G3D_PLL_CON0, exynos4415_pll_rates),
+ PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "fin_pll",
+ ISP_PLL_LOCK, ISP_PLL_CON0, exynos4415_pll_rates),
+ PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll",
+ "fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, exynos4415_pll_rates),
+};
+
+static struct samsung_cmu_info cmu_info __initdata = {
+ .pll_clks = exynos4415_plls,
+ .nr_pll_clks = ARRAY_SIZE(exynos4415_plls),
+ .mux_clks = exynos4415_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(exynos4415_mux_clks),
+ .div_clks = exynos4415_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos4415_div_clks),
+ .gate_clks = exynos4415_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(exynos4415_gate_clks),
+ .fixed_clks = exynos4415_fixed_rate_clks,
+ .nr_fixed_clks = ARRAY_SIZE(exynos4415_fixed_rate_clks),
+ .fixed_factor_clks = exynos4415_fixed_factor_clks,
+ .nr_fixed_factor_clks = ARRAY_SIZE(exynos4415_fixed_factor_clks),
+ .nr_clk_ids = CLK_NR_CLKS,
+ .clk_regs = exynos4415_cmu_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(exynos4415_cmu_clk_regs),
};
static void __init exynos4415_cmu_init(struct device_node *np)
{
- void __iomem *reg_base;
-
- reg_base = of_iomap(np, 0);
- if (!reg_base)
- panic("%s: failed to map registers\n", __func__);
-
- exynos4415_ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
- if (!exynos4415_ctx)
- panic("%s: unable to allocate context.\n", __func__);
-
- exynos4415_plls[apll].rate_table = exynos4415_pll_rates;
- exynos4415_plls[epll].rate_table = exynos4415_epll_rates;
- exynos4415_plls[g3d_pll].rate_table = exynos4415_pll_rates;
- exynos4415_plls[isp_pll].rate_table = exynos4415_pll_rates;
- exynos4415_plls[disp_pll].rate_table = exynos4415_pll_rates;
-
- samsung_clk_register_fixed_factor(exynos4415_ctx,
- exynos4415_fixed_factor_clks,
- ARRAY_SIZE(exynos4415_fixed_factor_clks));
- samsung_clk_register_fixed_rate(exynos4415_ctx,
- exynos4415_fixed_rate_clks,
- ARRAY_SIZE(exynos4415_fixed_rate_clks));
-
- samsung_clk_register_pll(exynos4415_ctx, exynos4415_plls,
- ARRAY_SIZE(exynos4415_plls), reg_base);
- samsung_clk_register_mux(exynos4415_ctx, exynos4415_mux_clks,
- ARRAY_SIZE(exynos4415_mux_clks));
- samsung_clk_register_div(exynos4415_ctx, exynos4415_div_clks,
- ARRAY_SIZE(exynos4415_div_clks));
- samsung_clk_register_gate(exynos4415_ctx, exynos4415_gate_clks,
- ARRAY_SIZE(exynos4415_gate_clks));
-
- exynos4415_clk_sleep_init();
-
- samsung_clk_of_add_provider(np, exynos4415_ctx);
+ samsung_cmu_register_one(np, &cmu_info);
}
CLK_OF_DECLARE(exynos4415_cmu, "samsung,exynos4415-cmu", exynos4415_cmu_init);
@@ -1027,16 +963,6 @@ CLK_OF_DECLARE(exynos4415_cmu, "samsung,exynos4415-cmu", exynos4415_cmu_init);
#define SRC_DMC 0x300
#define DIV_DMC1 0x504
-enum exynos4415_dmc_plls {
- mpll, bpll,
- nr_dmc_plls,
-};
-
-static struct samsung_clk_provider *exynos4415_dmc_ctx;
-
-#ifdef CONFIG_PM_SLEEP
-static struct samsung_clk_reg_dump *exynos4415_dmc_clk_regs;
-
static unsigned long exynos4415_cmu_dmc_clk_regs[] __initdata = {
MPLL_LOCK,
MPLL_CON0,
@@ -1050,42 +976,6 @@ static unsigned long exynos4415_cmu_dmc_clk_regs[] __initdata = {
DIV_DMC1,
};
-static int exynos4415_dmc_clk_suspend(void)
-{
- samsung_clk_save(exynos4415_dmc_ctx->reg_base,
- exynos4415_dmc_clk_regs,
- ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs));
- return 0;
-}
-
-static void exynos4415_dmc_clk_resume(void)
-{
- samsung_clk_restore(exynos4415_dmc_ctx->reg_base,
- exynos4415_dmc_clk_regs,
- ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs));
-}
-
-static struct syscore_ops exynos4415_dmc_clk_syscore_ops = {
- .suspend = exynos4415_dmc_clk_suspend,
- .resume = exynos4415_dmc_clk_resume,
-};
-
-static void exynos4415_dmc_clk_sleep_init(void)
-{
- exynos4415_dmc_clk_regs =
- samsung_clk_alloc_reg_dump(exynos4415_cmu_dmc_clk_regs,
- ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs));
- if (!exynos4415_dmc_clk_regs) {
- pr_warn("%s: Failed to allocate sleep save data\n", __func__);
- return;
- }
-
- register_syscore_ops(&exynos4415_dmc_clk_syscore_ops);
-}
-#else
-static inline void exynos4415_dmc_clk_sleep_init(void) { }
-#endif /* CONFIG_PM_SLEEP */
-
PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", };
PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", };
PNAME(mbpll_p) = { "mout_mpll", "mout_bpll", };
@@ -1107,38 +997,28 @@ static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = {
DIV(CLK_DMC_DIV_MPLL_PRE, "div_mpll_pre", "mout_mpll", DIV_DMC1, 8, 2),
};
-static struct samsung_pll_clock exynos4415_dmc_plls[nr_dmc_plls] __initdata = {
- [mpll] = PLL(pll_35xx, CLK_DMC_FOUT_MPLL, "fout_mpll", "fin_pll",
- MPLL_LOCK, MPLL_CON0, NULL),
- [bpll] = PLL(pll_35xx, CLK_DMC_FOUT_BPLL, "fout_bpll", "fin_pll",
- BPLL_LOCK, BPLL_CON0, NULL),
+static struct samsung_pll_clock exynos4415_dmc_plls[] __initdata = {
+ PLL(pll_35xx, CLK_DMC_FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON0, exynos4415_pll_rates),
+ PLL(pll_35xx, CLK_DMC_FOUT_BPLL, "fout_bpll", "fin_pll",
+ BPLL_LOCK, BPLL_CON0, exynos4415_pll_rates),
+};
+
+static struct samsung_cmu_info cmu_dmc_info __initdata = {
+ .pll_clks = exynos4415_dmc_plls,
+ .nr_pll_clks = ARRAY_SIZE(exynos4415_dmc_plls),
+ .mux_clks = exynos4415_dmc_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(exynos4415_dmc_mux_clks),
+ .div_clks = exynos4415_dmc_div_clks,
+ .nr_div_clks = ARRAY_SIZE(exynos4415_dmc_div_clks),
+ .nr_clk_ids = NR_CLKS_DMC,
+ .clk_regs = exynos4415_cmu_dmc_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(exynos4415_cmu_dmc_clk_regs),
};
static void __init exynos4415_cmu_dmc_init(struct device_node *np)
{
- void __iomem *reg_base;
-
- reg_base = of_iomap(np, 0);
- if (!reg_base)
- panic("%s: failed to map registers\n", __func__);
-
- exynos4415_dmc_ctx = samsung_clk_init(np, reg_base, NR_CLKS_DMC);
- if (!exynos4415_dmc_ctx)
- panic("%s: unable to allocate context.\n", __func__);
-
- exynos4415_dmc_plls[mpll].rate_table = exynos4415_pll_rates;
- exynos4415_dmc_plls[bpll].rate_table = exynos4415_pll_rates;
-
- samsung_clk_register_pll(exynos4415_dmc_ctx, exynos4415_dmc_plls,
- ARRAY_SIZE(exynos4415_dmc_plls), reg_base);
- samsung_clk_register_mux(exynos4415_dmc_ctx, exynos4415_dmc_mux_clks,
- ARRAY_SIZE(exynos4415_dmc_mux_clks));
- samsung_clk_register_div(exynos4415_dmc_ctx, exynos4415_dmc_div_clks,
- ARRAY_SIZE(exynos4415_dmc_div_clks));
-
- exynos4415_dmc_clk_sleep_init();
-
- samsung_clk_of_add_provider(np, exynos4415_dmc_ctx);
+ samsung_cmu_register_one(np, &cmu_dmc_info);
}
CLK_OF_DECLARE(exynos4415_cmu_dmc, "samsung,exynos4415-cmu-dmc",
exynos4415_cmu_dmc_init);
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index ea4483b8d62e8a..03d36e847b78e0 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -34,6 +34,7 @@
#define DIV_TOPC0 0x0600
#define DIV_TOPC1 0x0604
#define DIV_TOPC3 0x060C
+#define ENABLE_ACLK_TOPC1 0x0804
static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
@@ -45,6 +46,7 @@ static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
};
/* List of parent clocks for Muxes in CMU_TOPC */
+PNAME(mout_aud_pll_ctrl_p) = { "fin_pll", "fout_aud_pll" };
PNAME(mout_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" };
PNAME(mout_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" };
PNAME(mout_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" };
@@ -104,9 +106,11 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = {
MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p,
MUX_SEL_TOPC1, 16, 1),
+ MUX(0, "mout_aud_pll_ctrl", mout_aud_pll_ctrl_p, MUX_SEL_TOPC1, 0, 1),
MUX(0, "mout_aclk_ccore_133", mout_topc_group2, MUX_SEL_TOPC2, 4, 2),
+ MUX(0, "mout_aclk_mscl_532", mout_topc_group2, MUX_SEL_TOPC3, 20, 2),
MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2),
};
@@ -114,6 +118,8 @@ static struct samsung_div_clock topc_div_clks[] __initdata = {
DIV(DOUT_ACLK_CCORE_133, "dout_aclk_ccore_133", "mout_aclk_ccore_133",
DIV_TOPC0, 4, 4),
+ DIV(DOUT_ACLK_MSCL_532, "dout_aclk_mscl_532", "mout_aclk_mscl_532",
+ DIV_TOPC1, 20, 4),
DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66",
DIV_TOPC1, 24, 4),
@@ -125,6 +131,18 @@ static struct samsung_div_clock topc_div_clks[] __initdata = {
DIV_TOPC3, 12, 3),
DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_mfc_pll_ctrl",
DIV_TOPC3, 16, 3),
+ DIV(DOUT_SCLK_AUD_PLL, "dout_sclk_aud_pll", "mout_aud_pll_ctrl",
+ DIV_TOPC3, 28, 3),
+};
+
+static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
+ PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
+ {},
+};
+
+static struct samsung_gate_clock topc_gate_clks[] __initdata = {
+ GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532",
+ ENABLE_ACLK_TOPC1, 20, 0, 0),
};
static struct samsung_pll_clock topc_pll_clks[] __initdata = {
@@ -136,8 +154,8 @@ static struct samsung_pll_clock topc_pll_clks[] __initdata = {
BUS1_DPLL_CON0, NULL),
PLL(pll_1452x, 0, "fout_mfc_pll", "fin_pll", MFC_PLL_LOCK,
MFC_PLL_CON0, NULL),
- PLL(pll_1460x, 0, "fout_aud_pll", "fin_pll", AUD_PLL_LOCK,
- AUD_PLL_CON0, NULL),
+ PLL(pll_1460x, FOUT_AUD_PLL, "fout_aud_pll", "fin_pll", AUD_PLL_LOCK,
+ AUD_PLL_CON0, pll1460x_24mhz_tbl),
};
static struct samsung_cmu_info topc_cmu_info __initdata = {
@@ -147,6 +165,8 @@ static struct samsung_cmu_info topc_cmu_info __initdata = {
.nr_mux_clks = ARRAY_SIZE(topc_mux_clks),
.div_clks = topc_div_clks,
.nr_div_clks = ARRAY_SIZE(topc_div_clks),
+ .gate_clks = topc_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(topc_gate_clks),
.fixed_factor_clks = topc_fixed_factor_clks,
.nr_fixed_factor_clks = ARRAY_SIZE(topc_fixed_factor_clks),
.nr_clk_ids = TOPC_NR_CLK,
@@ -166,9 +186,18 @@ CLK_OF_DECLARE(exynos7_clk_topc, "samsung,exynos7-clock-topc",
#define MUX_SEL_TOP00 0x0200
#define MUX_SEL_TOP01 0x0204
#define MUX_SEL_TOP03 0x020C
+#define MUX_SEL_TOP0_PERIC0 0x0230
+#define MUX_SEL_TOP0_PERIC1 0x0234
+#define MUX_SEL_TOP0_PERIC2 0x0238
#define MUX_SEL_TOP0_PERIC3 0x023C
#define DIV_TOP03 0x060C
+#define DIV_TOP0_PERIC0 0x0630
+#define DIV_TOP0_PERIC1 0x0634
+#define DIV_TOP0_PERIC2 0x0638
#define DIV_TOP0_PERIC3 0x063C
+#define ENABLE_SCLK_TOP0_PERIC0 0x0A30
+#define ENABLE_SCLK_TOP0_PERIC1 0x0A34
+#define ENABLE_SCLK_TOP0_PERIC2 0x0A38
#define ENABLE_SCLK_TOP0_PERIC3 0x0A3C
/* List of parent clocks for Muxes in CMU_TOP0 */
@@ -176,6 +205,7 @@ PNAME(mout_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" };
PNAME(mout_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll" };
PNAME(mout_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll" };
PNAME(mout_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll" };
+PNAME(mout_aud_pll_p) = { "fin_pll", "dout_sclk_aud_pll" };
PNAME(mout_top0_half_bus0_pll_p) = {"mout_top0_bus0_pll",
"ffac_top0_bus0_pll_div2"};
@@ -189,18 +219,34 @@ PNAME(mout_top0_half_mfc_pll_p) = {"mout_top0_mfc_pll",
PNAME(mout_top0_group1) = {"mout_top0_half_bus0_pll",
"mout_top0_half_bus1_pll", "mout_top0_half_cc_pll",
"mout_top0_half_mfc_pll"};
+PNAME(mout_top0_group3) = {"ioclk_audiocdclk0",
+ "ioclk_audiocdclk1", "ioclk_spdif_extclk",
+ "mout_top0_aud_pll", "mout_top0_half_bus0_pll",
+ "mout_top0_half_bus1_pll"};
+PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll",
+ "mout_top0_half_bus0_pll", "mout_top0_half_bus1_pll"};
static unsigned long top0_clk_regs[] __initdata = {
MUX_SEL_TOP00,
MUX_SEL_TOP01,
MUX_SEL_TOP03,
+ MUX_SEL_TOP0_PERIC0,
+ MUX_SEL_TOP0_PERIC1,
+ MUX_SEL_TOP0_PERIC2,
MUX_SEL_TOP0_PERIC3,
DIV_TOP03,
+ DIV_TOP0_PERIC0,
+ DIV_TOP0_PERIC1,
+ DIV_TOP0_PERIC2,
DIV_TOP0_PERIC3,
+ ENABLE_SCLK_TOP0_PERIC0,
+ ENABLE_SCLK_TOP0_PERIC1,
+ ENABLE_SCLK_TOP0_PERIC2,
ENABLE_SCLK_TOP0_PERIC3,
};
static struct samsung_mux_clock top0_mux_clks[] __initdata = {
+ MUX(0, "mout_top0_aud_pll", mout_aud_pll_p, MUX_SEL_TOP00, 0, 1),
MUX(0, "mout_top0_mfc_pll", mout_mfc_pll_p, MUX_SEL_TOP00, 4, 1),
MUX(0, "mout_top0_cc_pll", mout_cc_pll_p, MUX_SEL_TOP00, 8, 1),
MUX(0, "mout_top0_bus1_pll", mout_bus1_pll_p, MUX_SEL_TOP00, 12, 1),
@@ -218,10 +264,20 @@ static struct samsung_mux_clock top0_mux_clks[] __initdata = {
MUX(0, "mout_aclk_peric1_66", mout_top0_group1, MUX_SEL_TOP03, 12, 2),
MUX(0, "mout_aclk_peric0_66", mout_top0_group1, MUX_SEL_TOP03, 20, 2),
+ MUX(0, "mout_sclk_spdif", mout_top0_group3, MUX_SEL_TOP0_PERIC0, 4, 3),
+ MUX(0, "mout_sclk_pcm1", mout_top0_group4, MUX_SEL_TOP0_PERIC0, 8, 2),
+ MUX(0, "mout_sclk_i2s1", mout_top0_group4, MUX_SEL_TOP0_PERIC0, 20, 2),
+
+ MUX(0, "mout_sclk_spi1", mout_top0_group1, MUX_SEL_TOP0_PERIC1, 8, 2),
+ MUX(0, "mout_sclk_spi0", mout_top0_group1, MUX_SEL_TOP0_PERIC1, 20, 2),
+
+ MUX(0, "mout_sclk_spi3", mout_top0_group1, MUX_SEL_TOP0_PERIC2, 8, 2),
+ MUX(0, "mout_sclk_spi2", mout_top0_group1, MUX_SEL_TOP0_PERIC2, 20, 2),
MUX(0, "mout_sclk_uart3", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 4, 2),
MUX(0, "mout_sclk_uart2", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 8, 2),
MUX(0, "mout_sclk_uart1", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 12, 2),
MUX(0, "mout_sclk_uart0", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 16, 2),
+ MUX(0, "mout_sclk_spi4", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 20, 2),
};
static struct samsung_div_clock top0_div_clks[] __initdata = {
@@ -230,13 +286,40 @@ static struct samsung_div_clock top0_div_clks[] __initdata = {
DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66",
DIV_TOP03, 20, 6),
+ DIV(0, "dout_sclk_spdif", "mout_sclk_spdif", DIV_TOP0_PERIC0, 4, 4),
+ DIV(0, "dout_sclk_pcm1", "mout_sclk_pcm1", DIV_TOP0_PERIC0, 8, 12),
+ DIV(0, "dout_sclk_i2s1", "mout_sclk_i2s1", DIV_TOP0_PERIC0, 20, 10),
+
+ DIV(0, "dout_sclk_spi1", "mout_sclk_spi1", DIV_TOP0_PERIC1, 8, 12),
+ DIV(0, "dout_sclk_spi0", "mout_sclk_spi0", DIV_TOP0_PERIC1, 20, 12),
+
+ DIV(0, "dout_sclk_spi3", "mout_sclk_spi3", DIV_TOP0_PERIC2, 8, 12),
+ DIV(0, "dout_sclk_spi2", "mout_sclk_spi2", DIV_TOP0_PERIC2, 20, 12),
+
DIV(0, "dout_sclk_uart3", "mout_sclk_uart3", DIV_TOP0_PERIC3, 4, 4),
DIV(0, "dout_sclk_uart2", "mout_sclk_uart2", DIV_TOP0_PERIC3, 8, 4),
DIV(0, "dout_sclk_uart1", "mout_sclk_uart1", DIV_TOP0_PERIC3, 12, 4),
DIV(0, "dout_sclk_uart0", "mout_sclk_uart0", DIV_TOP0_PERIC3, 16, 4),
+ DIV(0, "dout_sclk_spi4", "mout_sclk_spi4", DIV_TOP0_PERIC3, 20, 12),
};
static struct samsung_gate_clock top0_gate_clks[] __initdata = {
+ GATE(CLK_SCLK_SPDIF, "sclk_spdif", "dout_sclk_spdif",
+ ENABLE_SCLK_TOP0_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_sclk_pcm1",
+ ENABLE_SCLK_TOP0_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_I2S1, "sclk_i2s1", "dout_sclk_i2s1",
+ ENABLE_SCLK_TOP0_PERIC0, 20, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_sclk_spi1",
+ ENABLE_SCLK_TOP0_PERIC1, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_sclk_spi0",
+ ENABLE_SCLK_TOP0_PERIC1, 20, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_SPI3, "sclk_spi3", "dout_sclk_spi3",
+ ENABLE_SCLK_TOP0_PERIC2, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_sclk_spi2",
+ ENABLE_SCLK_TOP0_PERIC2, 20, CLK_SET_RATE_PARENT, 0),
GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_sclk_uart3",
ENABLE_SCLK_TOP0_PERIC3, 4, 0, 0),
GATE(CLK_SCLK_UART2, "sclk_uart2", "dout_sclk_uart2",
@@ -245,6 +328,8 @@ static struct samsung_gate_clock top0_gate_clks[] __initdata = {
ENABLE_SCLK_TOP0_PERIC3, 12, 0, 0),
GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_sclk_uart0",
ENABLE_SCLK_TOP0_PERIC3, 16, 0, 0),
+ GATE(CLK_SCLK_SPI4, "sclk_spi4", "dout_sclk_spi4",
+ ENABLE_SCLK_TOP0_PERIC3, 20, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
@@ -343,6 +428,8 @@ static struct samsung_mux_clock top1_mux_clks[] __initdata = {
MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2),
MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 24, 2),
+ MUX(0, "mout_sclk_usbdrd300", mout_top1_group1,
+ MUX_SEL_TOP1_FSYS0, 28, 2),
MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 24, 2),
MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 28, 2),
@@ -356,6 +443,8 @@ static struct samsung_div_clock top1_div_clks[] __initdata = {
DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2",
DIV_TOP1_FSYS0, 24, 4),
+ DIV(0, "dout_sclk_usbdrd300", "mout_sclk_usbdrd300",
+ DIV_TOP1_FSYS0, 28, 4),
DIV(DOUT_SCLK_MMC1, "dout_sclk_mmc1", "mout_sclk_mmc1",
DIV_TOP1_FSYS1, 24, 4),
@@ -366,6 +455,8 @@ static struct samsung_div_clock top1_div_clks[] __initdata = {
static struct samsung_gate_clock top1_gate_clks[] __initdata = {
GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2",
ENABLE_SCLK_TOP1_FSYS0, 24, CLK_SET_RATE_PARENT, 0),
+ GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300",
+ ENABLE_SCLK_TOP1_FSYS0, 28, 0, 0),
GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1",
ENABLE_SCLK_TOP1_FSYS1, 24, CLK_SET_RATE_PARENT, 0),
@@ -514,6 +605,7 @@ static void __init exynos7_clk_peric0_init(struct device_node *np)
/* Register Offset definitions for CMU_PERIC1 (0x14C80000) */
#define MUX_SEL_PERIC10 0x0200
#define MUX_SEL_PERIC11 0x0204
+#define MUX_SEL_PERIC12 0x0208
#define ENABLE_PCLK_PERIC1 0x0900
#define ENABLE_SCLK_PERIC10 0x0A00
@@ -525,10 +617,16 @@ PNAME(mout_aclk_peric1_66_p) = { "fin_pll", "dout_aclk_peric1_66" };
PNAME(mout_sclk_uart1_p) = { "fin_pll", "sclk_uart1" };
PNAME(mout_sclk_uart2_p) = { "fin_pll", "sclk_uart2" };
PNAME(mout_sclk_uart3_p) = { "fin_pll", "sclk_uart3" };
+PNAME(mout_sclk_spi0_p) = { "fin_pll", "sclk_spi0" };
+PNAME(mout_sclk_spi1_p) = { "fin_pll", "sclk_spi1" };
+PNAME(mout_sclk_spi2_p) = { "fin_pll", "sclk_spi2" };
+PNAME(mout_sclk_spi3_p) = { "fin_pll", "sclk_spi3" };
+PNAME(mout_sclk_spi4_p) = { "fin_pll", "sclk_spi4" };
static unsigned long peric1_clk_regs[] __initdata = {
MUX_SEL_PERIC10,
MUX_SEL_PERIC11,
+ MUX_SEL_PERIC12,
ENABLE_PCLK_PERIC1,
ENABLE_SCLK_PERIC10,
};
@@ -537,6 +635,16 @@ static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_p,
MUX_SEL_PERIC10, 0, 1),
+ MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_p,
+ MUX_SEL_PERIC11, 0, 1, CLK_SET_RATE_PARENT, 0),
+ MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_p,
+ MUX_SEL_PERIC11, 4, 1, CLK_SET_RATE_PARENT, 0),
+ MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_p,
+ MUX_SEL_PERIC11, 8, 1, CLK_SET_RATE_PARENT, 0),
+ MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_p,
+ MUX_SEL_PERIC11, 12, 1, CLK_SET_RATE_PARENT, 0),
+ MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_p,
+ MUX_SEL_PERIC11, 16, 1, CLK_SET_RATE_PARENT, 0),
MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_p,
MUX_SEL_PERIC11, 20, 1),
MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_p,
@@ -562,6 +670,22 @@ static struct samsung_gate_clock peric1_gate_clks[] __initdata = {
ENABLE_PCLK_PERIC1, 10, 0, 0),
GATE(PCLK_UART3, "pclk_uart3", "mout_aclk_peric1_66_user",
ENABLE_PCLK_PERIC1, 11, 0, 0),
+ GATE(PCLK_SPI0, "pclk_spi0", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 12, 0, 0),
+ GATE(PCLK_SPI1, "pclk_spi1", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 13, 0, 0),
+ GATE(PCLK_SPI2, "pclk_spi2", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 14, 0, 0),
+ GATE(PCLK_SPI3, "pclk_spi3", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 15, 0, 0),
+ GATE(PCLK_SPI4, "pclk_spi4", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 16, 0, 0),
+ GATE(PCLK_I2S1, "pclk_i2s1", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 17, CLK_SET_RATE_PARENT, 0),
+ GATE(PCLK_PCM1, "pclk_pcm1", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 18, 0, 0),
+ GATE(PCLK_SPDIF, "pclk_spdif", "mout_aclk_peric1_66_user",
+ ENABLE_PCLK_PERIC1, 19, 0, 0),
GATE(SCLK_UART1, "sclk_uart1_user", "mout_sclk_uart1_user",
ENABLE_SCLK_PERIC10, 9, 0, 0),
@@ -569,6 +693,22 @@ static struct samsung_gate_clock peric1_gate_clks[] __initdata = {
ENABLE_SCLK_PERIC10, 10, 0, 0),
GATE(SCLK_UART3, "sclk_uart3_user", "mout_sclk_uart3_user",
ENABLE_SCLK_PERIC10, 11, 0, 0),
+ GATE(SCLK_SPI0, "sclk_spi0_user", "mout_sclk_spi0_user",
+ ENABLE_SCLK_PERIC10, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI1, "sclk_spi1_user", "mout_sclk_spi1_user",
+ ENABLE_SCLK_PERIC10, 13, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI2, "sclk_spi2_user", "mout_sclk_spi2_user",
+ ENABLE_SCLK_PERIC10, 14, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI3, "sclk_spi3_user", "mout_sclk_spi3_user",
+ ENABLE_SCLK_PERIC10, 15, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI4, "sclk_spi4_user", "mout_sclk_spi4_user",
+ ENABLE_SCLK_PERIC10, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_I2S1, "sclk_i2s1_user", "sclk_i2s1",
+ ENABLE_SCLK_PERIC10, 17, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_PCM1, "sclk_pcm1_user", "sclk_pcm1",
+ ENABLE_SCLK_PERIC10, 18, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPDIF, "sclk_spdif_user", "sclk_spdif",
+ ENABLE_SCLK_PERIC10, 19, CLK_SET_RATE_PARENT, 0),
};
static struct samsung_cmu_info peric1_cmu_info __initdata = {
@@ -647,7 +787,12 @@ CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris",
/* Register Offset definitions for CMU_FSYS0 (0x10E90000) */
#define MUX_SEL_FSYS00 0x0200
#define MUX_SEL_FSYS01 0x0204
+#define MUX_SEL_FSYS02 0x0208
+#define ENABLE_ACLK_FSYS00 0x0800
#define ENABLE_ACLK_FSYS01 0x0804
+#define ENABLE_SCLK_FSYS01 0x0A04
+#define ENABLE_SCLK_FSYS02 0x0A08
+#define ENABLE_SCLK_FSYS04 0x0A10
/*
* List of parent clocks for Muxes in CMU_FSYS0
@@ -655,10 +800,29 @@ CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris",
PNAME(mout_aclk_fsys0_200_p) = { "fin_pll", "dout_aclk_fsys0_200" };
PNAME(mout_sclk_mmc2_p) = { "fin_pll", "sclk_mmc2" };
+PNAME(mout_sclk_usbdrd300_p) = { "fin_pll", "sclk_usbdrd300" };
+PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_p) = { "fin_pll",
+ "phyclk_usbdrd300_udrd30_phyclock" };
+PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_p) = { "fin_pll",
+ "phyclk_usbdrd300_udrd30_pipe_pclk" };
+
+/* fixed rate clocks used in the FSYS0 block */
+struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
+ FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL,
+ CLK_IS_ROOT, 60000000),
+ FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL,
+ CLK_IS_ROOT, 125000000),
+};
+
static unsigned long fsys0_clk_regs[] __initdata = {
MUX_SEL_FSYS00,
MUX_SEL_FSYS01,
+ MUX_SEL_FSYS02,
+ ENABLE_ACLK_FSYS00,
ENABLE_ACLK_FSYS01,
+ ENABLE_SCLK_FSYS01,
+ ENABLE_SCLK_FSYS02,
+ ENABLE_SCLK_FSYS04,
};
static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
@@ -666,11 +830,49 @@ static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
MUX_SEL_FSYS00, 24, 1),
MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_p, MUX_SEL_FSYS01, 24, 1),
+ MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_p,
+ MUX_SEL_FSYS01, 28, 1),
+
+ MUX(0, "mout_phyclk_usbdrd300_udrd30_pipe_pclk_user",
+ mout_phyclk_usbdrd300_udrd30_pipe_pclk_p,
+ MUX_SEL_FSYS02, 24, 1),
+ MUX(0, "mout_phyclk_usbdrd300_udrd30_phyclk_user",
+ mout_phyclk_usbdrd300_udrd30_phyclk_p,
+ MUX_SEL_FSYS02, 28, 1),
};
static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
+ GATE(ACLK_AXIUS_USBDRD30X_FSYS0X, "aclk_axius_usbdrd30x_fsys0x",
+ "mout_aclk_fsys0_200_user",
+ ENABLE_ACLK_FSYS00, 19, 0, 0),
+ GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user",
+ ENABLE_ACLK_FSYS00, 3, 0, 0),
+ GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user",
+ ENABLE_ACLK_FSYS00, 4, 0, 0),
+
+ GATE(ACLK_USBDRD300, "aclk_usbdrd300", "mout_aclk_fsys0_200_user",
+ ENABLE_ACLK_FSYS01, 29, 0, 0),
GATE(ACLK_MMC2, "aclk_mmc2", "mout_aclk_fsys0_200_user",
ENABLE_ACLK_FSYS01, 31, 0, 0),
+
+ GATE(SCLK_USBDRD300_SUSPENDCLK, "sclk_usbdrd300_suspendclk",
+ "mout_sclk_usbdrd300_user",
+ ENABLE_SCLK_FSYS01, 4, 0, 0),
+ GATE(SCLK_USBDRD300_REFCLK, "sclk_usbdrd300_refclk", "fin_pll",
+ ENABLE_SCLK_FSYS01, 8, 0, 0),
+
+ GATE(PHYCLK_USBDRD300_UDRD30_PIPE_PCLK_USER,
+ "phyclk_usbdrd300_udrd30_pipe_pclk_user",
+ "mout_phyclk_usbdrd300_udrd30_pipe_pclk_user",
+ ENABLE_SCLK_FSYS02, 24, 0, 0),
+ GATE(PHYCLK_USBDRD300_UDRD30_PHYCLK_USER,
+ "phyclk_usbdrd300_udrd30_phyclk_user",
+ "mout_phyclk_usbdrd300_udrd30_phyclk_user",
+ ENABLE_SCLK_FSYS02, 28, 0, 0),
+
+ GATE(OSCCLK_PHY_CLKOUT_USB30_PHY, "oscclk_phy_clkout_usb30_phy",
+ "fin_pll",
+ ENABLE_SCLK_FSYS04, 28, 0, 0),
};
static struct samsung_cmu_info fsys0_cmu_info __initdata = {
@@ -741,3 +943,205 @@ static void __init exynos7_clk_fsys1_init(struct device_node *np)
CLK_OF_DECLARE(exynos7_clk_fsys1, "samsung,exynos7-clock-fsys1",
exynos7_clk_fsys1_init);
+
+#define MUX_SEL_MSCL 0x0200
+#define DIV_MSCL 0x0600
+#define ENABLE_ACLK_MSCL 0x0800
+#define ENABLE_PCLK_MSCL 0x0900
+
+/* List of parent clocks for Muxes in CMU_MSCL */
+PNAME(mout_aclk_mscl_532_user_p) = { "fin_pll", "aclk_mscl_532" };
+
+static unsigned long mscl_clk_regs[] __initdata = {
+ MUX_SEL_MSCL,
+ DIV_MSCL,
+ ENABLE_ACLK_MSCL,
+ ENABLE_PCLK_MSCL,
+};
+
+static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
+ MUX(USERMUX_ACLK_MSCL_532, "usermux_aclk_mscl_532",
+ mout_aclk_mscl_532_user_p, MUX_SEL_MSCL, 0, 1),
+};
+static struct samsung_div_clock mscl_div_clks[] __initdata = {
+ DIV(DOUT_PCLK_MSCL, "dout_pclk_mscl", "usermux_aclk_mscl_532",
+ DIV_MSCL, 0, 3),
+};
+static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
+
+ GATE(ACLK_MSCL_0, "aclk_mscl_0", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 31, 0, 0),
+ GATE(ACLK_MSCL_1, "aclk_mscl_1", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 30, 0, 0),
+ GATE(ACLK_JPEG, "aclk_jpeg", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 29, 0, 0),
+ GATE(ACLK_G2D, "aclk_g2d", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 28, 0, 0),
+ GATE(ACLK_LH_ASYNC_SI_MSCL_0, "aclk_lh_async_si_mscl_0",
+ "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 27, 0, 0),
+ GATE(ACLK_LH_ASYNC_SI_MSCL_1, "aclk_lh_async_si_mscl_1",
+ "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 26, 0, 0),
+ GATE(ACLK_XIU_MSCLX_0, "aclk_xiu_msclx_0", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 25, 0, 0),
+ GATE(ACLK_XIU_MSCLX_1, "aclk_xiu_msclx_1", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 24, 0, 0),
+ GATE(ACLK_AXI2ACEL_BRIDGE, "aclk_axi2acel_bridge",
+ "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 23, 0, 0),
+ GATE(ACLK_QE_MSCL_0, "aclk_qe_mscl_0", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 22, 0, 0),
+ GATE(ACLK_QE_MSCL_1, "aclk_qe_mscl_1", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 21, 0, 0),
+ GATE(ACLK_QE_JPEG, "aclk_qe_jpeg", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 20, 0, 0),
+ GATE(ACLK_QE_G2D, "aclk_qe_g2d", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 19, 0, 0),
+ GATE(ACLK_PPMU_MSCL_0, "aclk_ppmu_mscl_0", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 18, 0, 0),
+ GATE(ACLK_PPMU_MSCL_1, "aclk_ppmu_mscl_1", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 17, 0, 0),
+ GATE(ACLK_MSCLNP_133, "aclk_msclnp_133", "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 16, 0, 0),
+ GATE(ACLK_AHB2APB_MSCL0P, "aclk_ahb2apb_mscl0p",
+ "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 15, 0, 0),
+ GATE(ACLK_AHB2APB_MSCL1P, "aclk_ahb2apb_mscl1p",
+ "usermux_aclk_mscl_532",
+ ENABLE_ACLK_MSCL, 14, 0, 0),
+
+ GATE(PCLK_MSCL_0, "pclk_mscl_0", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 31, 0, 0),
+ GATE(PCLK_MSCL_1, "pclk_mscl_1", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 30, 0, 0),
+ GATE(PCLK_JPEG, "pclk_jpeg", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 29, 0, 0),
+ GATE(PCLK_G2D, "pclk_g2d", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 28, 0, 0),
+ GATE(PCLK_QE_MSCL_0, "pclk_qe_mscl_0", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 27, 0, 0),
+ GATE(PCLK_QE_MSCL_1, "pclk_qe_mscl_1", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 26, 0, 0),
+ GATE(PCLK_QE_JPEG, "pclk_qe_jpeg", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 25, 0, 0),
+ GATE(PCLK_QE_G2D, "pclk_qe_g2d", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 24, 0, 0),
+ GATE(PCLK_PPMU_MSCL_0, "pclk_ppmu_mscl_0", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 23, 0, 0),
+ GATE(PCLK_PPMU_MSCL_1, "pclk_ppmu_mscl_1", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 22, 0, 0),
+ GATE(PCLK_AXI2ACEL_BRIDGE, "pclk_axi2acel_bridge", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 21, 0, 0),
+ GATE(PCLK_PMU_MSCL, "pclk_pmu_mscl", "dout_pclk_mscl",
+ ENABLE_PCLK_MSCL, 20, 0, 0),
+};
+
+static struct samsung_cmu_info mscl_cmu_info __initdata = {
+ .mux_clks = mscl_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(mscl_mux_clks),
+ .div_clks = mscl_div_clks,
+ .nr_div_clks = ARRAY_SIZE(mscl_div_clks),
+ .gate_clks = mscl_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(mscl_gate_clks),
+ .nr_clk_ids = MSCL_NR_CLK,
+ .clk_regs = mscl_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(mscl_clk_regs),
+};
+
+static void __init exynos7_clk_mscl_init(struct device_node *np)
+{
+ samsung_cmu_register_one(np, &mscl_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos7_clk_mscl, "samsung,exynos7-clock-mscl",
+ exynos7_clk_mscl_init);
+
+/* Register Offset definitions for CMU_AUD (0x114C0000) */
+#define MUX_SEL_AUD 0x0200
+#define DIV_AUD0 0x0600
+#define DIV_AUD1 0x0604
+#define ENABLE_ACLK_AUD 0x0800
+#define ENABLE_PCLK_AUD 0x0900
+#define ENABLE_SCLK_AUD 0x0A00
+
+/*
+ * List of parent clocks for Muxes in CMU_AUD
+ */
+PNAME(mout_aud_pll_user_p) = { "fin_pll", "fout_aud_pll" };
+PNAME(mout_aud_group_p) = { "dout_aud_cdclk", "ioclk_audiocdclk0" };
+
+static unsigned long aud_clk_regs[] __initdata = {
+ MUX_SEL_AUD,
+ DIV_AUD0,
+ DIV_AUD1,
+ ENABLE_ACLK_AUD,
+ ENABLE_PCLK_AUD,
+ ENABLE_SCLK_AUD,
+};
+
+static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+ MUX(0, "mout_sclk_i2s", mout_aud_group_p, MUX_SEL_AUD, 12, 1),
+ MUX(0, "mout_sclk_pcm", mout_aud_group_p, MUX_SEL_AUD, 16, 1),
+ MUX(0, "mout_aud_pll_user", mout_aud_pll_user_p, MUX_SEL_AUD, 20, 1),
+};
+
+static struct samsung_div_clock aud_div_clks[] __initdata = {
+ DIV(0, "dout_aud_ca5", "mout_aud_pll_user", DIV_AUD0, 0, 4),
+ DIV(0, "dout_aclk_aud", "dout_aud_ca5", DIV_AUD0, 4, 4),
+ DIV(0, "dout_aud_pclk_dbg", "dout_aud_ca5", DIV_AUD0, 8, 4),
+
+ DIV(0, "dout_sclk_i2s", "mout_sclk_i2s", DIV_AUD1, 0, 4),
+ DIV(0, "dout_sclk_pcm", "mout_sclk_pcm", DIV_AUD1, 4, 8),
+ DIV(0, "dout_sclk_uart", "dout_aud_cdclk", DIV_AUD1, 12, 4),
+ DIV(0, "dout_sclk_slimbus", "dout_aud_cdclk", DIV_AUD1, 16, 5),
+ DIV(0, "dout_aud_cdclk", "mout_aud_pll_user", DIV_AUD1, 24, 4),
+};
+
+static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+ GATE(SCLK_PCM, "sclk_pcm", "dout_sclk_pcm",
+ ENABLE_SCLK_AUD, 27, CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_I2S, "sclk_i2s", "dout_sclk_i2s",
+ ENABLE_SCLK_AUD, 28, CLK_SET_RATE_PARENT, 0),
+ GATE(0, "sclk_uart", "dout_sclk_uart", ENABLE_SCLK_AUD, 29, 0, 0),
+ GATE(0, "sclk_slimbus", "dout_sclk_slimbus",
+ ENABLE_SCLK_AUD, 30, 0, 0),
+
+ GATE(0, "pclk_dbg_aud", "dout_aud_pclk_dbg", ENABLE_PCLK_AUD, 19, 0, 0),
+ GATE(0, "pclk_gpio_aud", "dout_aclk_aud", ENABLE_PCLK_AUD, 20, 0, 0),
+ GATE(0, "pclk_wdt1", "dout_aclk_aud", ENABLE_PCLK_AUD, 22, 0, 0),
+ GATE(0, "pclk_wdt0", "dout_aclk_aud", ENABLE_PCLK_AUD, 23, 0, 0),
+ GATE(0, "pclk_slimbus", "dout_aclk_aud", ENABLE_PCLK_AUD, 24, 0, 0),
+ GATE(0, "pclk_uart", "dout_aclk_aud", ENABLE_PCLK_AUD, 25, 0, 0),
+ GATE(PCLK_PCM, "pclk_pcm", "dout_aclk_aud",
+ ENABLE_PCLK_AUD, 26, CLK_SET_RATE_PARENT, 0),
+ GATE(PCLK_I2S, "pclk_i2s", "dout_aclk_aud",
+ ENABLE_PCLK_AUD, 27, CLK_SET_RATE_PARENT, 0),
+ GATE(0, "pclk_timer", "dout_aclk_aud", ENABLE_PCLK_AUD, 28, 0, 0),
+ GATE(0, "pclk_smmu_aud", "dout_aclk_aud", ENABLE_PCLK_AUD, 31, 0, 0),
+
+ GATE(0, "aclk_smmu_aud", "dout_aclk_aud", ENABLE_ACLK_AUD, 27, 0, 0),
+ GATE(0, "aclk_acel_lh_async_si_top", "dout_aclk_aud",
+ ENABLE_ACLK_AUD, 28, 0, 0),
+ GATE(ACLK_ADMA, "aclk_dmac", "dout_aclk_aud", ENABLE_ACLK_AUD, 31, 0, 0),
+};
+
+static struct samsung_cmu_info aud_cmu_info __initdata = {
+ .mux_clks = aud_mux_clks,
+ .nr_mux_clks = ARRAY_SIZE(aud_mux_clks),
+ .div_clks = aud_div_clks,
+ .nr_div_clks = ARRAY_SIZE(aud_div_clks),
+ .gate_clks = aud_gate_clks,
+ .nr_gate_clks = ARRAY_SIZE(aud_gate_clks),
+ .nr_clk_ids = AUD_NR_CLK,
+ .clk_regs = aud_clk_regs,
+ .nr_clk_regs = ARRAY_SIZE(aud_clk_regs),
+};
+
+static void __init exynos7_clk_aud_init(struct device_node *np)
+{
+ samsung_cmu_register_one(np, &aud_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos7_clk_aud, "samsung,exynos7-clock-aud",
+ exynos7_clk_aud_init);
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 4bda54095a16a0..9e1f88c04fd46d 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -374,19 +374,24 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
* Common function which registers plls, muxes, dividers and gates
* for each CMU. It also add CMU register list to register cache.
*/
-void __init samsung_cmu_register_one(struct device_node *np,
+struct samsung_clk_provider * __init samsung_cmu_register_one(
+ struct device_node *np,
struct samsung_cmu_info *cmu)
{
void __iomem *reg_base;
struct samsung_clk_provider *ctx;
reg_base = of_iomap(np, 0);
- if (!reg_base)
+ if (!reg_base) {
panic("%s: failed to map registers\n", __func__);
+ return NULL;
+ }
ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
- if (!ctx)
+ if (!ctx) {
panic("%s: unable to alllocate ctx\n", __func__);
+ return ctx;
+ }
if (cmu->pll_clks)
samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks,
@@ -410,4 +415,6 @@ void __init samsung_cmu_register_one(struct device_node *np,
cmu->nr_clk_regs);
samsung_clk_of_add_provider(np, ctx);
+
+ return ctx;
}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 8acabe1f32c4d4..e4c75383cea718 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -392,7 +392,8 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
struct samsung_pll_clock *pll_list,
unsigned int nr_clk, void __iomem *base);
-extern void __init samsung_cmu_register_one(struct device_node *,
+extern struct samsung_clk_provider __init *samsung_cmu_register_one(
+ struct device_node *,
struct samsung_cmu_info *);
extern unsigned long _get_rate(const char *clk_name);
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile
index f83980f2b9568f..0689d7fb2666b1 100644
--- a/drivers/clk/shmobile/Makefile
+++ b/drivers/clk/shmobile/Makefile
@@ -1,9 +1,11 @@
obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
+obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
+obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c
index 639241e31e03ec..036a692c72195d 100644
--- a/drivers/clk/shmobile/clk-div6.c
+++ b/drivers/clk/shmobile/clk-div6.c
@@ -54,12 +54,19 @@ static int cpg_div6_clock_enable(struct clk_hw *hw)
static void cpg_div6_clock_disable(struct clk_hw *hw)
{
struct div6_clock *clock = to_div6_clock(hw);
+ u32 val;
- /* DIV6 clocks require the divisor field to be non-zero when stopping
- * the clock.
+ val = clk_readl(clock->reg);
+ val |= CPG_DIV6_CKSTP;
+ /*
+ * DIV6 clocks require the divisor field to be non-zero when stopping
+ * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be
+ * re-enabled later if the divisor field is changed when stopping the
+ * clock
*/
- clk_writel(clk_readl(clock->reg) | CPG_DIV6_CKSTP | CPG_DIV6_DIV_MASK,
- clock->reg);
+ if (!(val & CPG_DIV6_DIV_MASK))
+ val |= CPG_DIV6_DIV_MASK;
+ clk_writel(val, clock->reg);
}
static int cpg_div6_clock_is_enabled(struct clk_hw *hw)
@@ -83,6 +90,9 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
{
unsigned int div;
+ if (!rate)
+ rate = 1;
+
div = DIV_ROUND_CLOSEST(parent_rate, rate);
return clamp_t(unsigned int, div, 1, 64);
}
diff --git a/drivers/clk/shmobile/clk-r8a73a4.c b/drivers/clk/shmobile/clk-r8a73a4.c
new file mode 100644
index 00000000000000..29b9a0b0012ad3
--- /dev/null
+++ b/drivers/clk/shmobile/clk-r8a73a4.c
@@ -0,0 +1,241 @@
+/*
+ * r8a73a4 Core CPG Clocks
+ *
+ * Copyright (C) 2014 Ulrich Hecht
+ *
+ * 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; version 2 of the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct r8a73a4_cpg {
+ struct clk_onecell_data data;
+ spinlock_t lock;
+ void __iomem *reg;
+};
+
+#define CPG_CKSCR 0xc0
+#define CPG_FRQCRA 0x00
+#define CPG_FRQCRB 0x04
+#define CPG_FRQCRC 0xe0
+#define CPG_PLL0CR 0xd8
+#define CPG_PLL1CR 0x28
+#define CPG_PLL2CR 0x2c
+#define CPG_PLL2HCR 0xe4
+#define CPG_PLL2SCR 0xf4
+
+#define CLK_ENABLE_ON_INIT BIT(0)
+
+struct div4_clk {
+ const char *name;
+ unsigned int reg;
+ unsigned int shift;
+};
+
+static struct div4_clk div4_clks[] = {
+ { "i", CPG_FRQCRA, 20 },
+ { "m3", CPG_FRQCRA, 12 },
+ { "b", CPG_FRQCRA, 8 },
+ { "m1", CPG_FRQCRA, 4 },
+ { "m2", CPG_FRQCRA, 0 },
+ { "zx", CPG_FRQCRB, 12 },
+ { "zs", CPG_FRQCRB, 8 },
+ { "hp", CPG_FRQCRB, 4 },
+ { NULL, 0, 0 },
+};
+
+static const struct clk_div_table div4_div_table[] = {
+ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
+ { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 },
+ { 12, 10 }, { 0, 0 }
+};
+
+static struct clk * __init
+r8a73a4_cpg_register_clock(struct device_node *np, struct r8a73a4_cpg *cpg,
+ const char *name)
+{
+ const struct clk_div_table *table = NULL;
+ const char *parent_name;
+ unsigned int shift, reg;
+ unsigned int mult = 1;
+ unsigned int div = 1;
+
+
+ if (!strcmp(name, "main")) {
+ u32 ckscr = clk_readl(cpg->reg + CPG_CKSCR);
+
+ switch ((ckscr >> 28) & 3) {
+ case 0: /* extal1 */
+ parent_name = of_clk_get_parent_name(np, 0);
+ break;
+ case 1: /* extal1 / 2 */
+ parent_name = of_clk_get_parent_name(np, 0);
+ div = 2;
+ break;
+ case 2: /* extal2 */
+ parent_name = of_clk_get_parent_name(np, 1);
+ break;
+ case 3: /* extal2 / 2 */
+ parent_name = of_clk_get_parent_name(np, 1);
+ div = 2;
+ break;
+ }
+ } else if (!strcmp(name, "pll0")) {
+ /* PLL0/1 are configurable multiplier clocks. Register them as
+ * fixed factor clocks for now as there's no generic multiplier
+ * clock implementation and we currently have no need to change
+ * the multiplier value.
+ */
+ u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+
+ parent_name = "main";
+ mult = ((value >> 24) & 0x7f) + 1;
+ if (value & BIT(20))
+ div = 2;
+ } else if (!strcmp(name, "pll1")) {
+ u32 value = clk_readl(cpg->reg + CPG_PLL1CR);
+
+ parent_name = "main";
+ /* XXX: enable bit? */
+ mult = ((value >> 24) & 0x7f) + 1;
+ if (value & BIT(7))
+ div = 2;
+ } else if (!strncmp(name, "pll2", 4)) {
+ u32 value, cr;
+
+ switch (name[4]) {
+ case 0:
+ cr = CPG_PLL2CR;
+ break;
+ case 's':
+ cr = CPG_PLL2SCR;
+ break;
+ case 'h':
+ cr = CPG_PLL2HCR;
+ break;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+ value = clk_readl(cpg->reg + cr);
+ switch ((value >> 5) & 7) {
+ case 0:
+ parent_name = "main";
+ div = 2;
+ break;
+ case 1:
+ parent_name = "extal2";
+ div = 2;
+ break;
+ case 3:
+ parent_name = "extal2";
+ div = 4;
+ break;
+ case 4:
+ parent_name = "main";
+ break;
+ case 5:
+ parent_name = "extal2";
+ break;
+ default:
+ pr_warn("%s: unexpected parent of %s\n", __func__,
+ name);
+ return ERR_PTR(-EINVAL);
+ }
+ /* XXX: enable bit? */
+ mult = ((value >> 24) & 0x7f) + 1;
+ } else if (!strcmp(name, "z") || !strcmp(name, "z2")) {
+ u32 shift = 8;
+
+ parent_name = "pll0";
+ if (name[1] == '2') {
+ div = 2;
+ shift = 0;
+ }
+ div *= 32;
+ mult = 0x20 - ((clk_readl(cpg->reg + CPG_FRQCRC) >> shift)
+ & 0x1f);
+ } else {
+ struct div4_clk *c;
+
+ for (c = div4_clks; c->name; c++) {
+ if (!strcmp(name, c->name))
+ break;
+ }
+ if (!c->name)
+ return ERR_PTR(-EINVAL);
+
+ parent_name = "pll1";
+ table = div4_div_table;
+ reg = c->reg;
+ shift = c->shift;
+ }
+
+ if (!table) {
+ return clk_register_fixed_factor(NULL, name, parent_name, 0,
+ mult, div);
+ } else {
+ return clk_register_divider_table(NULL, name, parent_name, 0,
+ cpg->reg + reg, shift, 4, 0,
+ table, &cpg->lock);
+ }
+}
+
+static void __init r8a73a4_cpg_clocks_init(struct device_node *np)
+{
+ struct r8a73a4_cpg *cpg;
+ struct clk **clks;
+ unsigned int i;
+ int num_clks;
+
+ num_clks = of_property_count_strings(np, "clock-output-names");
+ if (num_clks < 0) {
+ pr_err("%s: failed to count clocks\n", __func__);
+ return;
+ }
+
+ cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
+ clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
+ if (cpg == NULL || clks == NULL) {
+ /* We're leaking memory on purpose, there's no point in cleaning
+ * up as the system won't boot anyway.
+ */
+ return;
+ }
+
+ spin_lock_init(&cpg->lock);
+
+ cpg->data.clks = clks;
+ cpg->data.clk_num = num_clks;
+
+ cpg->reg = of_iomap(np, 0);
+ if (WARN_ON(cpg->reg == NULL))
+ return;
+
+ for (i = 0; i < num_clks; ++i) {
+ const char *name;
+ struct clk *clk;
+
+ of_property_read_string_index(np, "clock-output-names", i,
+ &name);
+
+ clk = r8a73a4_cpg_register_clock(np, cpg, name);
+ if (IS_ERR(clk))
+ pr_err("%s: failed to register %s %s clock (%ld)\n",
+ __func__, np->name, name, PTR_ERR(clk));
+ else
+ cpg->data.clks[i] = clk;
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
+}
+CLK_OF_DECLARE(r8a73a4_cpg_clks, "renesas,r8a73a4-cpg-clocks",
+ r8a73a4_cpg_clocks_init);
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c
index e996425d06a920..acfb6d7dbd6bc0 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -33,6 +33,8 @@ struct rcar_gen2_cpg {
#define CPG_FRQCRC 0x000000e0
#define CPG_FRQCRC_ZFC_MASK (0x1f << 8)
#define CPG_FRQCRC_ZFC_SHIFT 8
+#define CPG_ADSPCKCR 0x0000025c
+#define CPG_RCANCKCR 0x00000270
/* -----------------------------------------------------------------------------
* Z Clock
@@ -161,6 +163,88 @@ static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg)
return clk;
}
+static struct clk * __init cpg_rcan_clk_register(struct rcar_gen2_cpg *cpg,
+ struct device_node *np)
+{
+ const char *parent_name = of_clk_get_parent_name(np, 1);
+ struct clk_fixed_factor *fixed;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+ if (!fixed)
+ return ERR_PTR(-ENOMEM);
+
+ fixed->mult = 1;
+ fixed->div = 6;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fixed);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = cpg->reg + CPG_RCANCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg->lock;
+
+ clk = clk_register_composite(NULL, "rcan", &parent_name, 1, NULL, NULL,
+ &fixed->hw, &clk_fixed_factor_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(fixed);
+ }
+
+ return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+ { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
+ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
+ { 10, 36 }, { 11, 48 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(struct rcar_gen2_cpg *cpg)
+{
+ const char *parent_name = "pll1";
+ struct clk_divider *div;
+ struct clk_gate *gate;
+ struct clk *clk;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = cpg->reg + CPG_ADSPCKCR;
+ div->width = 4;
+ div->table = cpg_adsp_div_table;
+ div->lock = &cpg->lock;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ gate->reg = cpg->reg + CPG_ADSPCKCR;
+ gate->bit_idx = 8;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ gate->lock = &cpg->lock;
+
+ clk = clk_register_composite(NULL, "adsp", &parent_name, 1, NULL, NULL,
+ &div->hw, &clk_divider_ops,
+ &gate->hw, &clk_gate_ops, 0);
+ if (IS_ERR(clk)) {
+ kfree(gate);
+ kfree(div);
+ }
+
+ return clk;
+}
+
/* -----------------------------------------------------------------------------
* CPG Clock Data
*/
@@ -263,6 +347,10 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
shift = 0;
} else if (!strcmp(name, "z")) {
return cpg_z_clk_register(cpg);
+ } else if (!strcmp(name, "rcan")) {
+ return cpg_rcan_clk_register(cpg, np);
+ } else if (!strcmp(name, "adsp")) {
+ return cpg_adsp_clk_register(cpg);
} else {
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 2282cef9f2ffb0..bf12a25eb3a22a 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -37,8 +37,8 @@ static int flexgen_enable(struct clk_hw *hw)
struct clk_hw *pgate_hw = &flexgen->pgate.hw;
struct clk_hw *fgate_hw = &flexgen->fgate.hw;
- pgate_hw->clk = hw->clk;
- fgate_hw->clk = hw->clk;
+ __clk_hw_set_clk(pgate_hw, hw);
+ __clk_hw_set_clk(fgate_hw, hw);
clk_gate_ops.enable(pgate_hw);
@@ -54,7 +54,7 @@ static void flexgen_disable(struct clk_hw *hw)
struct clk_hw *fgate_hw = &flexgen->fgate.hw;
/* disable only the final gate */
- fgate_hw->clk = hw->clk;
+ __clk_hw_set_clk(fgate_hw, hw);
clk_gate_ops.disable(fgate_hw);
@@ -66,7 +66,7 @@ static int flexgen_is_enabled(struct clk_hw *hw)
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *fgate_hw = &flexgen->fgate.hw;
- fgate_hw->clk = hw->clk;
+ __clk_hw_set_clk(fgate_hw, hw);
if (!clk_gate_ops.is_enabled(fgate_hw))
return 0;
@@ -79,7 +79,7 @@ static u8 flexgen_get_parent(struct clk_hw *hw)
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *mux_hw = &flexgen->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return clk_mux_ops.get_parent(mux_hw);
}
@@ -89,7 +89,7 @@ static int flexgen_set_parent(struct clk_hw *hw, u8 index)
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *mux_hw = &flexgen->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return clk_mux_ops.set_parent(mux_hw, index);
}
@@ -124,8 +124,8 @@ unsigned long flexgen_recalc_rate(struct clk_hw *hw,
struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
unsigned long mid_rate;
- pdiv_hw->clk = hw->clk;
- fdiv_hw->clk = hw->clk;
+ __clk_hw_set_clk(pdiv_hw, hw);
+ __clk_hw_set_clk(fdiv_hw, hw);
mid_rate = clk_divider_ops.recalc_rate(pdiv_hw, parent_rate);
@@ -138,16 +138,27 @@ static int flexgen_set_rate(struct clk_hw *hw, unsigned long rate,
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
- unsigned long primary_div = 0;
+ unsigned long div = 0;
int ret = 0;
- pdiv_hw->clk = hw->clk;
- fdiv_hw->clk = hw->clk;
+ __clk_hw_set_clk(pdiv_hw, hw);
+ __clk_hw_set_clk(fdiv_hw, hw);
- primary_div = clk_best_div(parent_rate, rate);
+ div = clk_best_div(parent_rate, rate);
- clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate);
- ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * primary_div);
+ /*
+ * pdiv is mainly targeted for low freq results, while fdiv
+ * should be used for div <= 64. The other way round can
+ * lead to 'duty cycle' issues.
+ */
+
+ if (div <= 64) {
+ clk_divider_ops.set_rate(pdiv_hw, parent_rate, parent_rate);
+ ret = clk_divider_ops.set_rate(fdiv_hw, rate, rate * div);
+ } else {
+ clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate);
+ ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * div);
+ }
return ret;
}
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 79dc40b5cc688f..9a15ec344a8590 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -94,7 +94,7 @@ static int clkgena_divmux_enable(struct clk_hw *hw)
unsigned long timeout;
int ret = 0;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel);
if (ret)
@@ -116,7 +116,7 @@ static void clkgena_divmux_disable(struct clk_hw *hw)
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF);
}
@@ -126,7 +126,7 @@ static int clkgena_divmux_is_enabled(struct clk_hw *hw)
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
}
@@ -136,7 +136,7 @@ u8 clkgena_divmux_get_parent(struct clk_hw *hw)
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
if ((s8)genamux->muxsel < 0) {
@@ -174,7 +174,7 @@ unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return clk_divider_ops.recalc_rate(div_hw, parent_rate);
}
@@ -185,7 +185,7 @@ static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate,
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return clk_divider_ops.set_rate(div_hw, rate, parent_rate);
}
@@ -196,7 +196,7 @@ static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate,
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return clk_divider_ops.round_rate(div_hw, rate, prate);
}
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index a66953c0f43094..3a5292e3fcf808 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -8,6 +8,7 @@ obj-y += clk-a20-gmac.o
obj-y += clk-mod0.o
obj-y += clk-sun8i-mbus.o
obj-y += clk-sun9i-core.o
+obj-y += clk-sun9i-mmc.o
obj-$(CONFIG_MFD_SUN6I_PRCM) += \
clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 62e08fb58554cb..8c20190a3e9f4e 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -80,6 +80,8 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
}
static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_p)
{
@@ -156,9 +158,10 @@ static const struct clk_ops clk_factors_ops = {
.set_rate = clk_factors_set_rate,
};
-struct clk * __init sunxi_factors_register(struct device_node *node,
- const struct factors_data *data,
- spinlock_t *lock)
+struct clk *sunxi_factors_register(struct device_node *node,
+ const struct factors_data *data,
+ spinlock_t *lock,
+ void __iomem *reg)
{
struct clk *clk;
struct clk_factors *factors;
@@ -168,11 +171,8 @@ struct clk * __init sunxi_factors_register(struct device_node *node,
struct clk_hw *mux_hw = NULL;
const char *clk_name = node->name;
const char *parents[FACTORS_MAX_PARENTS];
- void __iomem *reg;
int i = 0;
- reg = of_iomap(node, 0);
-
/* if we have a mux, we will have >1 parents */
while (i < FACTORS_MAX_PARENTS &&
(parents[i] = of_clk_get_parent_name(node, i)) != NULL)
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 912238fde13242..171085ab5513e4 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -36,8 +36,9 @@ struct clk_factors {
spinlock_t *lock;
};
-struct clk * __init sunxi_factors_register(struct device_node *node,
- const struct factors_data *data,
- spinlock_t *lock);
+struct clk *sunxi_factors_register(struct device_node *node,
+ const struct factors_data *data,
+ spinlock_t *lock,
+ void __iomem *reg);
#endif
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index da0524eaee9406..ec8f5a1fca09f4 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include "clk-factors.h"
@@ -67,7 +68,7 @@ static struct clk_factors_config sun4i_a10_mod0_config = {
.pwidth = 2,
};
-static const struct factors_data sun4i_a10_mod0_data __initconst = {
+static const struct factors_data sun4i_a10_mod0_data = {
.enable = 31,
.mux = 24,
.muxmask = BIT(1) | BIT(0),
@@ -79,15 +80,95 @@ static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
static void __init sun4i_a10_mod0_setup(struct device_node *node)
{
- sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
+ void __iomem *reg;
+
+ reg = of_iomap(node, 0);
+ if (!reg) {
+ /*
+ * This happens with mod0 clk nodes instantiated through
+ * mfd, as those do not have their resources assigned at
+ * CLK_OF_DECLARE time yet, so do not print an error.
+ */
+ return;
+ }
+
+ sunxi_factors_register(node, &sun4i_a10_mod0_data,
+ &sun4i_a10_mod0_lock, reg);
}
CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
+static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *r;
+ void __iomem *reg;
+
+ if (!np)
+ return -ENODEV;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ sunxi_factors_register(np, &sun4i_a10_mod0_data,
+ &sun4i_a10_mod0_lock, reg);
+ return 0;
+}
+
+static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = {
+ { .compatible = "allwinner,sun4i-a10-mod0-clk" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun4i_a10_mod0_clk_driver = {
+ .driver = {
+ .name = "sun4i-a10-mod0-clk",
+ .of_match_table = sun4i_a10_mod0_clk_dt_ids,
+ },
+ .probe = sun4i_a10_mod0_clk_probe,
+};
+module_platform_driver(sun4i_a10_mod0_clk_driver);
+
+static const struct factors_data sun9i_a80_mod0_data __initconst = {
+ .enable = 31,
+ .mux = 24,
+ .muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
+ .table = &sun4i_a10_mod0_config,
+ .getter = sun4i_a10_get_mod0_factors,
+};
+
+static void __init sun9i_a80_mod0_setup(struct device_node *node)
+{
+ void __iomem *reg;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg)) {
+ pr_err("Could not get registers for mod0-clk: %s\n",
+ node->name);
+ return;
+ }
+
+ sunxi_factors_register(node, &sun9i_a80_mod0_data,
+ &sun4i_a10_mod0_lock, reg);
+}
+CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup);
+
static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
static void __init sun5i_a13_mbus_setup(struct device_node *node)
{
- struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock);
+ struct clk *mbus;
+ void __iomem *reg;
+
+ reg = of_iomap(node, 0);
+ if (!reg) {
+ pr_err("Could not get registers for a13-mbus-clk\n");
+ return;
+ }
+
+ mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data,
+ &sun5i_a13_mbus_lock, reg);
/* The MBUS clocks needs to be always enabled */
__clk_get(mbus);
@@ -95,14 +176,10 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node)
}
CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
-struct mmc_phase_data {
- u8 offset;
-};
-
struct mmc_phase {
struct clk_hw hw;
+ u8 offset;
void __iomem *reg;
- struct mmc_phase_data *data;
spinlock_t *lock;
};
@@ -118,7 +195,7 @@ static int mmc_get_phase(struct clk_hw *hw)
u8 delay;
value = readl(phase->reg);
- delay = (value >> phase->data->offset) & 0x3;
+ delay = (value >> phase->offset) & 0x3;
if (!delay)
return 180;
@@ -206,8 +283,8 @@ static int mmc_set_phase(struct clk_hw *hw, int degrees)
spin_lock_irqsave(phase->lock, flags);
value = readl(phase->reg);
- value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
- value |= delay << phase->data->offset;
+ value &= ~GENMASK(phase->offset + 3, phase->offset);
+ value |= delay << phase->offset;
writel(value, phase->reg);
spin_unlock_irqrestore(phase->lock, flags);
@@ -219,66 +296,97 @@ static const struct clk_ops mmc_clk_ops = {
.set_phase = mmc_set_phase,
};
-static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
- struct mmc_phase_data *data)
+/*
+ * sunxi_mmc_setup - Common setup function for mmc module clocks
+ *
+ * The only difference between module clocks on different platforms is the
+ * width of the mux register bits and the valid values, which are passed in
+ * through struct factors_data. The phase clocks parts are identical.
+ */
+static void __init sunxi_mmc_setup(struct device_node *node,
+ const struct factors_data *data,
+ spinlock_t *lock)
{
- const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
- struct clk_init_data init = {
- .num_parents = 1,
- .parent_names = parent_names,
- .ops = &mmc_clk_ops,
- };
-
- struct mmc_phase *phase;
- struct clk *clk;
-
- phase = kmalloc(sizeof(*phase), GFP_KERNEL);
- if (!phase)
+ struct clk_onecell_data *clk_data;
+ const char *parent;
+ void __iomem *reg;
+ int i;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg)) {
+ pr_err("Couldn't map the %s clock registers\n", node->name);
return;
+ }
- phase->hw.init = &init;
-
- phase->reg = of_iomap(node, 0);
- if (!phase->reg)
- goto err_free;
-
- phase->data = data;
- phase->lock = &sun4i_a10_mod0_lock;
-
- if (of_property_read_string(node, "clock-output-names", &init.name))
- init.name = node->name;
+ clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ return;
- clk = clk_register(NULL, &phase->hw);
- if (IS_ERR(clk))
- goto err_unmap;
+ clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL);
+ if (!clk_data->clks)
+ goto err_free_data;
+
+ clk_data->clk_num = 3;
+ clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg);
+ if (!clk_data->clks[0])
+ goto err_free_clks;
+
+ parent = __clk_get_name(clk_data->clks[0]);
+
+ for (i = 1; i < 3; i++) {
+ struct clk_init_data init = {
+ .num_parents = 1,
+ .parent_names = &parent,
+ .ops = &mmc_clk_ops,
+ };
+ struct mmc_phase *phase;
+
+ phase = kmalloc(sizeof(*phase), GFP_KERNEL);
+ if (!phase)
+ continue;
+
+ phase->hw.init = &init;
+ phase->reg = reg;
+ phase->lock = lock;
+
+ if (i == 1)
+ phase->offset = 8;
+ else
+ phase->offset = 20;
+
+ if (of_property_read_string_index(node, "clock-output-names",
+ i, &init.name))
+ init.name = node->name;
+
+ clk_data->clks[i] = clk_register(NULL, &phase->hw);
+ if (IS_ERR(clk_data->clks[i])) {
+ kfree(phase);
+ continue;
+ }
+ }
- of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
return;
-err_unmap:
- iounmap(phase->reg);
-err_free:
- kfree(phase);
+err_free_clks:
+ kfree(clk_data->clks);
+err_free_data:
+ kfree(clk_data);
}
+static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
-static struct mmc_phase_data mmc_output_clk = {
- .offset = 8,
-};
-
-static struct mmc_phase_data mmc_sample_clk = {
- .offset = 20,
-};
-
-static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
+static void __init sun4i_a10_mmc_setup(struct device_node *node)
{
- sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
+ sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock);
}
-CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
+CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
+
+static DEFINE_SPINLOCK(sun9i_a80_mmc_lock);
-static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
+static void __init sun9i_a80_mmc_setup(struct device_node *node)
{
- sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
+ sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock);
}
-CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
+CLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup);
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 3d282fb8f85cc2..63cf149195ae1a 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -45,6 +45,8 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
}
static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
diff --git a/drivers/clk/sunxi/clk-sun8i-mbus.c b/drivers/clk/sunxi/clk-sun8i-mbus.c
index ef49786eefd3ca..14cd026064bf37 100644
--- a/drivers/clk/sunxi/clk-sun8i-mbus.c
+++ b/drivers/clk/sunxi/clk-sun8i-mbus.c
@@ -69,8 +69,17 @@ static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
static void __init sun8i_a23_mbus_setup(struct device_node *node)
{
- struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
- &sun8i_a23_mbus_lock);
+ struct clk *mbus;
+ void __iomem *reg;
+
+ reg = of_iomap(node, 0);
+ if (!reg) {
+ pr_err("Could not get registers for a23-mbus-clk\n");
+ return;
+ }
+
+ mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
+ &sun8i_a23_mbus_lock, reg);
/* The MBUS clocks needs to be always enabled */
__clk_get(mbus);
diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
index 3cb9036d91bb20..d8da77d72861b2 100644
--- a/drivers/clk/sunxi/clk-sun9i-core.c
+++ b/drivers/clk/sunxi/clk-sun9i-core.c
@@ -24,50 +24,51 @@
/**
- * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1
+ * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL4
* PLL4 rate is calculated as follows
* rate = (parent_rate * n >> p) / (m + 1);
- * parent_rate is always 24Mhz
+ * parent_rate is always 24MHz
*
* p and m are named div1 and div2 in Allwinner's SDK
*/
static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate,
- u8 *n, u8 *k, u8 *m, u8 *p)
+ u8 *n_ret, u8 *k, u8 *m_ret, u8 *p_ret)
{
- int div;
+ int n;
+ int m = 1;
+ int p = 1;
- /* Normalize value to a 6M multiple */
- div = DIV_ROUND_UP(*freq, 6000000);
+ /* Normalize value to a 6 MHz multiple (24 MHz / 4) */
+ n = DIV_ROUND_UP(*freq, 6000000);
- /* divs above 256 cannot be odd */
- if (div > 256)
- div = round_up(div, 2);
+ /* If n is too large switch to steps of 12 MHz */
+ if (n > 255) {
+ m = 0;
+ n = (n + 1) / 2;
+ }
+
+ /* If n is still too large switch to steps of 24 MHz */
+ if (n > 255) {
+ p = 0;
+ n = (n + 1) / 2;
+ }
- /* divs above 512 must be a multiple of 4 */
- if (div > 512)
- div = round_up(div, 4);
+ /* n must be between 12 and 255 */
+ if (n > 255)
+ n = 255;
+ else if (n < 12)
+ n = 12;
- *freq = 6000000 * div;
+ *freq = ((24000000 * n) >> p) / (m + 1);
/* we were called to round the frequency, we can now return */
- if (n == NULL)
+ if (n_ret == NULL)
return;
- /* p will be 1 for divs under 512 */
- if (div < 512)
- *p = 1;
- else
- *p = 0;
-
- /* m will be 1 if div is odd */
- if (div & 1)
- *m = 1;
- else
- *m = 0;
-
- /* calculate a suitable n based on m and p */
- *n = div / (*p + 1) / (*m + 1);
+ *n_ret = n;
+ *m_ret = m;
+ *p_ret = p;
}
static struct clk_factors_config sun9i_a80_pll4_config = {
@@ -89,7 +90,17 @@ static DEFINE_SPINLOCK(sun9i_a80_pll4_lock);
static void __init sun9i_a80_pll4_setup(struct device_node *node)
{
- sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock);
+ void __iomem *reg;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (!reg) {
+ pr_err("Could not get registers for a80-pll4-clk: %s\n",
+ node->name);
+ return;
+ }
+
+ sunxi_factors_register(node, &sun9i_a80_pll4_data,
+ &sun9i_a80_pll4_lock, reg);
}
CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup);
@@ -139,8 +150,18 @@ static DEFINE_SPINLOCK(sun9i_a80_gt_lock);
static void __init sun9i_a80_gt_setup(struct device_node *node)
{
- struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
- &sun9i_a80_gt_lock);
+ void __iomem *reg;
+ struct clk *gt;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (!reg) {
+ pr_err("Could not get registers for a80-gt-clk: %s\n",
+ node->name);
+ return;
+ }
+
+ gt = sunxi_factors_register(node, &sun9i_a80_gt_data,
+ &sun9i_a80_gt_lock, reg);
/* The GT bus clock needs to be always enabled */
__clk_get(gt);
@@ -194,7 +215,17 @@ static DEFINE_SPINLOCK(sun9i_a80_ahb_lock);
static void __init sun9i_a80_ahb_setup(struct device_node *node)
{
- sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock);
+ void __iomem *reg;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (!reg) {
+ pr_err("Could not get registers for a80-ahb-clk: %s\n",
+ node->name);
+ return;
+ }
+
+ sunxi_factors_register(node, &sun9i_a80_ahb_data,
+ &sun9i_a80_ahb_lock, reg);
}
CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup);
@@ -210,7 +241,17 @@ static DEFINE_SPINLOCK(sun9i_a80_apb0_lock);
static void __init sun9i_a80_apb0_setup(struct device_node *node)
{
- sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock);
+ void __iomem *reg;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (!reg) {
+ pr_err("Could not get registers for a80-apb0-clk: %s\n",
+ node->name);
+ return;
+ }
+
+ sunxi_factors_register(node, &sun9i_a80_apb0_data,
+ &sun9i_a80_apb0_lock, reg);
}
CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup);
@@ -266,6 +307,16 @@ static DEFINE_SPINLOCK(sun9i_a80_apb1_lock);
static void __init sun9i_a80_apb1_setup(struct device_node *node)
{
- sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock);
+ void __iomem *reg;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (!reg) {
+ pr_err("Could not get registers for a80-apb1-clk: %s\n",
+ node->name);
+ return;
+ }
+
+ sunxi_factors_register(node, &sun9i_a80_apb1_data,
+ &sun9i_a80_apb1_lock, reg);
}
CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c
new file mode 100644
index 00000000000000..710c273648d709
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun9i-mmc.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2015 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define SUN9I_MMC_WIDTH 4
+
+#define SUN9I_MMC_GATE_BIT 16
+#define SUN9I_MMC_RESET_BIT 18
+
+struct sun9i_mmc_clk_data {
+ spinlock_t lock;
+ void __iomem *membase;
+ struct clk *clk;
+ struct reset_control *reset;
+ struct clk_onecell_data clk_data;
+ struct reset_controller_dev rcdev;
+};
+
+static int sun9i_mmc_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct sun9i_mmc_clk_data *data = container_of(rcdev,
+ struct sun9i_mmc_clk_data,
+ rcdev);
+ unsigned long flags;
+ void __iomem *reg = data->membase + SUN9I_MMC_WIDTH * id;
+ u32 val;
+
+ clk_prepare_enable(data->clk);
+ spin_lock_irqsave(&data->lock, flags);
+
+ val = readl(reg);
+ writel(val & ~BIT(SUN9I_MMC_RESET_BIT), reg);
+
+ spin_unlock_irqrestore(&data->lock, flags);
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+}
+
+static int sun9i_mmc_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct sun9i_mmc_clk_data *data = container_of(rcdev,
+ struct sun9i_mmc_clk_data,
+ rcdev);
+ unsigned long flags;
+ void __iomem *reg = data->membase + SUN9I_MMC_WIDTH * id;
+ u32 val;
+
+ clk_prepare_enable(data->clk);
+ spin_lock_irqsave(&data->lock, flags);
+
+ val = readl(reg);
+ writel(val | BIT(SUN9I_MMC_RESET_BIT), reg);
+
+ spin_unlock_irqrestore(&data->lock, flags);
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+}
+
+static struct reset_control_ops sun9i_mmc_reset_ops = {
+ .assert = sun9i_mmc_reset_assert,
+ .deassert = sun9i_mmc_reset_deassert,
+};
+
+static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct sun9i_mmc_clk_data *data;
+ struct clk_onecell_data *clk_data;
+ const char *clk_name = np->name;
+ const char *clk_parent;
+ struct resource *r;
+ int count, i, ret;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock_init(&data->lock);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ /* one clock/reset pair per word */
+ count = DIV_ROUND_UP((r->end - r->start + 1), SUN9I_MMC_WIDTH);
+ data->membase = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(data->membase))
+ return PTR_ERR(data->membase);
+
+ clk_data = &data->clk_data;
+ clk_data->clk_num = count;
+ clk_data->clks = devm_kcalloc(&pdev->dev, count, sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!clk_data->clks)
+ return -ENOMEM;
+
+ data->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(data->clk)) {
+ dev_err(&pdev->dev, "Could not get clock\n");
+ return PTR_ERR(data->clk);
+ }
+
+ data->reset = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(data->reset)) {
+ dev_err(&pdev->dev, "Could not get reset control\n");
+ return PTR_ERR(data->reset);
+ }
+
+ ret = reset_control_deassert(data->reset);
+ if (ret) {
+ dev_err(&pdev->dev, "Reset deassert err %d\n", ret);
+ return ret;
+ }
+
+ clk_parent = __clk_get_name(data->clk);
+ for (i = 0; i < count; i++) {
+ of_property_read_string_index(np, "clock-output-names",
+ i, &clk_name);
+
+ clk_data->clks[i] = clk_register_gate(&pdev->dev, clk_name,
+ clk_parent, 0,
+ data->membase + SUN9I_MMC_WIDTH * i,
+ SUN9I_MMC_GATE_BIT, 0,
+ &data->lock);
+
+ if (IS_ERR(clk_data->clks[i])) {
+ ret = PTR_ERR(clk_data->clks[i]);
+ goto err_clk_register;
+ }
+ }
+
+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+ if (ret)
+ goto err_clk_provider;
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = count;
+ data->rcdev.ops = &sun9i_mmc_reset_ops;
+ data->rcdev.of_node = pdev->dev.of_node;
+
+ ret = reset_controller_register(&data->rcdev);
+ if (ret)
+ goto err_rc_reg;
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+
+err_rc_reg:
+ of_clk_del_provider(np);
+
+err_clk_provider:
+ for (i = 0; i < count; i++)
+ clk_unregister(clk_data->clks[i]);
+
+err_clk_register:
+ reset_control_assert(data->reset);
+
+ return ret;
+}
+
+static int sun9i_a80_mmc_config_clk_remove(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct sun9i_mmc_clk_data *data = platform_get_drvdata(pdev);
+ struct clk_onecell_data *clk_data = &data->clk_data;
+ int i;
+
+ reset_controller_unregister(&data->rcdev);
+ of_clk_del_provider(np);
+ for (i = 0; i < clk_data->clk_num; i++)
+ clk_unregister(clk_data->clks[i]);
+
+ reset_control_assert(data->reset);
+
+ return 0;
+}
+
+static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = {
+ { .compatible = "allwinner,sun9i-a80-mmc-config-clk" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun9i_a80_mmc_config_clk_driver = {
+ .driver = {
+ .name = "sun9i-a80-mmc-config-clk",
+ .of_match_table = sun9i_a80_mmc_config_clk_dt_ids,
+ },
+ .probe = sun9i_a80_mmc_config_clk_probe,
+ .remove = sun9i_a80_mmc_config_clk_remove,
+};
+module_platform_driver(sun9i_a80_mmc_config_clk_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai ");
+MODULE_DESCRIPTION("Allwinner A80 MMC clock/reset Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 1818f404538d37..379324eb5486e1 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -20,11 +20,221 @@
#include
#include
#include
+#include
#include "clk-factors.h"
static DEFINE_SPINLOCK(clk_lock);
+/**
+ * sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk
+ */
+
+#define SUN6I_AHB1_MAX_PARENTS 4
+#define SUN6I_AHB1_MUX_PARENT_PLL6 3
+#define SUN6I_AHB1_MUX_SHIFT 12
+/* un-shifted mask is what mux_clk expects */
+#define SUN6I_AHB1_MUX_MASK 0x3
+#define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \
+ SUN6I_AHB1_MUX_MASK)
+
+#define SUN6I_AHB1_DIV_SHIFT 4
+#define SUN6I_AHB1_DIV_MASK (0x3 << SUN6I_AHB1_DIV_SHIFT)
+#define SUN6I_AHB1_DIV_GET(reg) ((reg & SUN6I_AHB1_DIV_MASK) >> \
+ SUN6I_AHB1_DIV_SHIFT)
+#define SUN6I_AHB1_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_DIV_MASK) | \
+ (div << SUN6I_AHB1_DIV_SHIFT))
+#define SUN6I_AHB1_PLL6_DIV_SHIFT 6
+#define SUN6I_AHB1_PLL6_DIV_MASK (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT)
+#define SUN6I_AHB1_PLL6_DIV_GET(reg) ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \
+ SUN6I_AHB1_PLL6_DIV_SHIFT)
+#define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | \
+ (div << SUN6I_AHB1_PLL6_DIV_SHIFT))
+
+struct sun6i_ahb1_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+};
+
+#define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw)
+
+static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw);
+ unsigned long rate;
+ u32 reg;
+
+ /* Fetch the register value */
+ reg = readl(ahb1->reg);
+
+ /* apply pre-divider first if parent is pll6 */
+ if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6)
+ parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1;
+
+ /* clk divider */
+ rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg);
+
+ return rate;
+}
+
+static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
+ u8 parent, unsigned long parent_rate)
+{
+ u8 div, calcp, calcm = 1;
+
+ /*
+ * clock can only divide, so we will never be able to achieve
+ * frequencies higher than the parent frequency
+ */
+ if (parent_rate && rate > parent_rate)
+ rate = parent_rate;
+
+ div = DIV_ROUND_UP(parent_rate, rate);
+
+ /* calculate pre-divider if parent is pll6 */
+ if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) {
+ if (div < 4)
+ calcp = 0;
+ else if (div / 2 < 4)
+ calcp = 1;
+ else if (div / 4 < 4)
+ calcp = 2;
+ else
+ calcp = 3;
+
+ calcm = DIV_ROUND_UP(div, 1 << calcp);
+ } else {
+ calcp = __roundup_pow_of_two(div);
+ calcp = calcp > 3 ? 3 : calcp;
+ }
+
+ /* we were asked to pass back divider values */
+ if (divp) {
+ *divp = calcp;
+ *pre_divp = calcm - 1;
+ }
+
+ return (parent_rate / calcm) >> calcp;
+}
+
+static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
+{
+ struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+ int i, num_parents;
+ unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
+
+ /* find the parent that can help provide the fastest rate <= rate */
+ num_parents = __clk_get_num_parents(clk);
+ for (i = 0; i < num_parents; i++) {
+ parent = clk_get_parent_by_index(clk, i);
+ if (!parent)
+ continue;
+ if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
+ parent_rate = __clk_round_rate(parent, rate);
+ else
+ parent_rate = __clk_get_rate(parent);
+
+ child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i,
+ parent_rate);
+
+ if (child_rate <= rate && child_rate > best_child_rate) {
+ best_parent = parent;
+ best = parent_rate;
+ best_child_rate = child_rate;
+ }
+ }
+
+ if (best_parent)
+ *best_parent_clk = __clk_get_hw(best_parent);
+ *best_parent_rate = best;
+
+ return best_child_rate;
+}
+
+static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw);
+ unsigned long flags;
+ u8 div, pre_div, parent;
+ u32 reg;
+
+ spin_lock_irqsave(&clk_lock, flags);
+
+ reg = readl(ahb1->reg);
+
+ /* need to know which parent is used to apply pre-divider */
+ parent = SUN6I_AHB1_MUX_GET_PARENT(reg);
+ sun6i_ahb1_clk_round(rate, &div, &pre_div, parent, parent_rate);
+
+ reg = SUN6I_AHB1_DIV_SET(reg, div);
+ reg = SUN6I_AHB1_PLL6_DIV_SET(reg, pre_div);
+ writel(reg, ahb1->reg);
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return 0;
+}
+
+static const struct clk_ops sun6i_ahb1_clk_ops = {
+ .determine_rate = sun6i_ahb1_clk_determine_rate,
+ .recalc_rate = sun6i_ahb1_clk_recalc_rate,
+ .set_rate = sun6i_ahb1_clk_set_rate,
+};
+
+static void __init sun6i_ahb1_clk_setup(struct device_node *node)
+{
+ struct clk *clk;
+ struct sun6i_ahb1_clk *ahb1;
+ struct clk_mux *mux;
+ const char *clk_name = node->name;
+ const char *parents[SUN6I_AHB1_MAX_PARENTS];
+ void __iomem *reg;
+ int i = 0;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+
+ /* we have a mux, we will have >1 parents */
+ while (i < SUN6I_AHB1_MAX_PARENTS &&
+ (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL);
+ if (!ahb1)
+ return;
+
+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+ if (!mux) {
+ kfree(ahb1);
+ return;
+ }
+
+ /* set up clock properties */
+ mux->reg = reg;
+ mux->shift = SUN6I_AHB1_MUX_SHIFT;
+ mux->mask = SUN6I_AHB1_MUX_MASK;
+ mux->lock = &clk_lock;
+ ahb1->reg = reg;
+
+ clk = clk_register_composite(NULL, clk_name, parents, i,
+ &mux->hw, &clk_mux_ops,
+ &ahb1->hw, &sun6i_ahb1_clk_ops,
+ NULL, NULL, 0);
+
+ 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(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_setup);
+
/* Maximum number of parents our clocks have */
#define SUNXI_MAX_PARENTS 5
@@ -354,43 +564,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
*p = calcp;
}
-/**
- * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
- */
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output)
-{
- #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
- #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
-
- struct clk_hw *hw = __clk_get_hw(clk);
- struct clk_composite *composite = to_clk_composite(hw);
- struct clk_hw *rate_hw = composite->rate_hw;
- struct clk_factors *factors = to_clk_factors(rate_hw);
- unsigned long flags = 0;
- u32 reg;
-
- if (factors->lock)
- spin_lock_irqsave(factors->lock, flags);
-
- reg = readl(factors->reg);
-
- /* set sample clock phase control */
- reg &= ~(0x7 << 20);
- reg |= ((sample & 0x7) << 20);
-
- /* set output clock phase control */
- reg &= ~(0x7 << 8);
- reg |= ((output & 0x7) << 8);
-
- writel(reg, factors->reg);
-
- if (factors->lock)
- spin_unlock_irqrestore(factors->lock, flags);
-}
-EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
-
-
/**
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
@@ -413,6 +586,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
.kwidth = 2,
.mshift = 0,
.mwidth = 2,
+ .n_start = 1,
};
static struct clk_factors_config sun8i_a23_pll1_config = {
@@ -520,7 +694,16 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
const struct factors_data *data)
{
- return sunxi_factors_register(node, data, &clk_lock);
+ void __iomem *reg;
+
+ reg = of_iomap(node, 0);
+ if (!reg) {
+ pr_err("Could not get registers for factors-clk: %s\n",
+ node->name);
+ return NULL;
+ }
+
+ return sunxi_factors_register(node, data, &clk_lock, reg);
}
@@ -561,7 +744,7 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
of_property_read_string(node, "clock-output-names", &clk_name);
clk = clk_register_mux(NULL, clk_name, parents, i,
- CLK_SET_RATE_NO_REPARENT, reg,
+ CLK_SET_RATE_PARENT, reg,
data->shift, SUNXI_MUX_GATE_WIDTH,
0, &clk_lock);
@@ -1217,7 +1400,6 @@ CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
static const char *sun6i_critical_clocks[] __initdata = {
"cpu",
- "ahb1_sdram",
};
static void __init sun6i_init_clocks(struct device_node *node)
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index f7dfb72884a4e2..edb8358fa6ceba 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
+obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index 0011d547a9f7ed..60738cc954cb3d 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -64,10 +64,8 @@ enum clk_id {
tegra_clk_disp2,
tegra_clk_dp2,
tegra_clk_dpaux,
- tegra_clk_dsia,
tegra_clk_dsialp,
tegra_clk_dsia_mux,
- tegra_clk_dsib,
tegra_clk_dsiblp,
tegra_clk_dsib_mux,
tegra_clk_dtv,
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 9e899c18af8678..d84ae49d0e05ee 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -28,7 +28,7 @@ static u8 clk_periph_get_parent(struct clk_hw *hw)
const struct clk_ops *mux_ops = periph->mux_ops;
struct clk_hw *mux_hw = &periph->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return mux_ops->get_parent(mux_hw);
}
@@ -39,7 +39,7 @@ static int clk_periph_set_parent(struct clk_hw *hw, u8 index)
const struct clk_ops *mux_ops = periph->mux_ops;
struct clk_hw *mux_hw = &periph->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return mux_ops->set_parent(mux_hw, index);
}
@@ -51,7 +51,7 @@ static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
const struct clk_ops *div_ops = periph->div_ops;
struct clk_hw *div_hw = &periph->divider.hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return div_ops->recalc_rate(div_hw, parent_rate);
}
@@ -63,7 +63,7 @@ static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *div_ops = periph->div_ops;
struct clk_hw *div_hw = &periph->divider.hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return div_ops->round_rate(div_hw, rate, prate);
}
@@ -75,7 +75,7 @@ static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *div_ops = periph->div_ops;
struct clk_hw *div_hw = &periph->divider.hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return div_ops->set_rate(div_hw, rate, parent_rate);
}
@@ -86,7 +86,7 @@ static int clk_periph_is_enabled(struct clk_hw *hw)
const struct clk_ops *gate_ops = periph->gate_ops;
struct clk_hw *gate_hw = &periph->gate.hw;
- gate_hw->clk = hw->clk;
+ __clk_hw_set_clk(gate_hw, hw);
return gate_ops->is_enabled(gate_hw);
}
@@ -97,7 +97,7 @@ static int clk_periph_enable(struct clk_hw *hw)
const struct clk_ops *gate_ops = periph->gate_ops;
struct clk_hw *gate_hw = &periph->gate.hw;
- gate_hw->clk = hw->clk;
+ __clk_hw_set_clk(gate_hw, hw);
return gate_ops->enable(gate_hw);
}
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index c7c6d8fb32fbb1..bfef9abdf23250 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -816,7 +816,9 @@ const struct clk_ops tegra_clk_plle_ops = {
.enable = clk_plle_enable,
};
-#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
+ defined(CONFIG_ARCH_TEGRA_124_SOC) || \
+ defined(CONFIG_ARCH_TEGRA_132_SOC)
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
unsigned long parent_rate)
@@ -1505,7 +1507,9 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
return clk;
}
-#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
+#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
+ defined(CONFIG_ARCH_TEGRA_124_SOC) || \
+ defined(CONFIG_ARCH_TEGRA_132_SOC)
static const struct clk_ops tegra_clk_pllxc_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pll_iddq_enable,
@@ -1565,7 +1569,7 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
- name, parent_name);
+ parent_name, name);
return ERR_PTR(-EINVAL);
}
@@ -1665,7 +1669,7 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
- name, parent_name);
+ parent_name, name);
return ERR_PTR(-EINVAL);
}
@@ -1706,7 +1710,7 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
- name, parent_name);
+ parent_name, name);
return ERR_PTR(-EINVAL);
}
@@ -1802,7 +1806,7 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
}
#endif
-#ifdef CONFIG_ARCH_TEGRA_124_SOC
+#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
static const struct clk_ops tegra_clk_pllss_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pll_iddq_enable,
@@ -1830,7 +1834,7 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
- name, parent_name);
+ parent_name, name);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index 37f32c49674eb2..cef0727b9eec98 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -434,10 +434,10 @@ static struct tegra_periph_init_data periph_clks[] = {
MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda),
MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
- MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1),
- MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2),
- MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3),
- MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4),
+ MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1),
+ MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2),
+ MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3),
+ MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4),
MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la),
MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace),
MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr),
@@ -470,10 +470,10 @@ static struct tegra_periph_init_data periph_clks[] = {
MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
- MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8),
- MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8),
- MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8),
- MUX8("sdmmc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4_8),
+ MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_8),
+ MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_8),
+ MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_8),
+ MUX8("sdmmc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4_8),
MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8),
MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8),
MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8),
@@ -537,8 +537,6 @@ static struct tegra_periph_init_data gate_clks[] = {
GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0),
GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0),
GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
- GATE("dsia", "dsia_mux", 48, 0, tegra_clk_dsia, 0),
- GATE("dsib", "dsib_mux", 82, 0, tegra_clk_dsib, 0),
GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 0b03d2cf7264f7..d0766423a5d607 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -715,7 +715,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_sbc2_8] = { .dt_id = TEGRA114_CLK_SBC2, .present = true },
[tegra_clk_sbc3_8] = { .dt_id = TEGRA114_CLK_SBC3, .present = true },
[tegra_clk_i2c5] = { .dt_id = TEGRA114_CLK_I2C5, .present = true },
- [tegra_clk_dsia] = { .dt_id = TEGRA114_CLK_DSIA, .present = true },
[tegra_clk_mipi] = { .dt_id = TEGRA114_CLK_MIPI, .present = true },
[tegra_clk_hdmi] = { .dt_id = TEGRA114_CLK_HDMI, .present = true },
[tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true },
@@ -739,7 +738,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_dtv] = { .dt_id = TEGRA114_CLK_DTV, .present = true },
[tegra_clk_ndspeed] = { .dt_id = TEGRA114_CLK_NDSPEED, .present = true },
[tegra_clk_i2cslow] = { .dt_id = TEGRA114_CLK_I2CSLOW, .present = true },
- [tegra_clk_dsib] = { .dt_id = TEGRA114_CLK_DSIB, .present = true },
[tegra_clk_tsec] = { .dt_id = TEGRA114_CLK_TSEC, .present = true },
[tegra_clk_xusb_host] = { .dt_id = TEGRA114_CLK_XUSB_HOST, .present = true },
[tegra_clk_msenc] = { .dt_id = TEGRA114_CLK_MSENC, .present = true },
@@ -1224,6 +1222,14 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
clks[TEGRA114_CLK_DSIB_MUX] = clk;
+ clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
+ 0, 48, periph_clk_enb_refcnt);
+ clks[TEGRA114_CLK_DSIA] = clk;
+
+ clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
+ 0, 82, periph_clk_enb_refcnt);
+ clks[TEGRA114_CLK_DSIB] = clk;
+
/* emc mux */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm),
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index f5f9baca7bb621..9a893f2fe8e988 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2014 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -28,6 +28,14 @@
#include "clk.h"
#include "clk-id.h"
+/*
+ * TEGRA124_CAR_BANK_COUNT: the number of peripheral clock register
+ * banks present in the Tegra124/132 CAR IP block. The banks are
+ * identified by single letters, e.g.: L, H, U, V, W, X. See
+ * periph_regs[] in drivers/clk/tegra/clk.c
+ */
+#define TEGRA124_CAR_BANK_COUNT 6
+
#define CLK_SOURCE_CSITE 0x1d4
#define CLK_SOURCE_EMC 0x19c
@@ -128,7 +136,6 @@ static unsigned long osc_freq;
static unsigned long pll_ref_freq;
static DEFINE_SPINLOCK(pll_d_lock);
-static DEFINE_SPINLOCK(pll_d2_lock);
static DEFINE_SPINLOCK(pll_e_lock);
static DEFINE_SPINLOCK(pll_re_lock);
static DEFINE_SPINLOCK(pll_u_lock);
@@ -145,11 +152,6 @@ static unsigned long tegra124_input_freq[] = {
[12] = 260000000,
};
-static const char *mux_plld_out0_plld2_out0[] = {
- "pll_d_out0", "pll_d2_out0",
-};
-#define mux_plld_out0_plld2_out0_idx NULL
-
static const char *mux_pllmcp_clkm[] = {
"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
};
@@ -783,7 +785,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_sbc2] = { .dt_id = TEGRA124_CLK_SBC2, .present = true },
[tegra_clk_sbc3] = { .dt_id = TEGRA124_CLK_SBC3, .present = true },
[tegra_clk_i2c5] = { .dt_id = TEGRA124_CLK_I2C5, .present = true },
- [tegra_clk_dsia] = { .dt_id = TEGRA124_CLK_DSIA, .present = true },
[tegra_clk_mipi] = { .dt_id = TEGRA124_CLK_MIPI, .present = true },
[tegra_clk_hdmi] = { .dt_id = TEGRA124_CLK_HDMI, .present = true },
[tegra_clk_csi] = { .dt_id = TEGRA124_CLK_CSI, .present = true },
@@ -809,7 +810,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_soc_therm] = { .dt_id = TEGRA124_CLK_SOC_THERM, .present = true },
[tegra_clk_dtv] = { .dt_id = TEGRA124_CLK_DTV, .present = true },
[tegra_clk_i2cslow] = { .dt_id = TEGRA124_CLK_I2CSLOW, .present = true },
- [tegra_clk_dsib] = { .dt_id = TEGRA124_CLK_DSIB, .present = true },
[tegra_clk_tsec] = { .dt_id = TEGRA124_CLK_TSEC, .present = true },
[tegra_clk_xusb_host] = { .dt_id = TEGRA124_CLK_XUSB_HOST, .present = true },
[tegra_clk_msenc] = { .dt_id = TEGRA124_CLK_MSENC, .present = true },
@@ -949,8 +949,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true },
[tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true },
[tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true },
- [tegra_clk_dsia_mux] = { .dt_id = TEGRA124_CLK_DSIA_MUX, .present = true },
- [tegra_clk_dsib_mux] = { .dt_id = TEGRA124_CLK_DSIB_MUX, .present = true },
};
static struct tegra_devclk devclks[] __initdata = {
@@ -1112,17 +1110,17 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
1, 2);
clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk;
- /* dsia mux */
- clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
- ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
- clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
- clks[TEGRA124_CLK_DSIA_MUX] = clk;
+ clk = clk_register_gate(NULL, "plld_dsi", "plld_out0", 0,
+ clk_base + PLLD_MISC, 30, 0, &pll_d_lock);
+ clks[TEGRA124_CLK_PLLD_DSI] = clk;
+
+ clk = tegra_clk_register_periph_gate("dsia", "plld_dsi", 0, clk_base,
+ 0, 48, periph_clk_enb_refcnt);
+ clks[TEGRA124_CLK_DSIA] = clk;
- /* dsib mux */
- clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
- ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
- clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
- clks[TEGRA124_CLK_DSIB_MUX] = clk;
+ clk = tegra_clk_register_periph_gate("dsib", "plld_dsi", 0, clk_base,
+ 0, 82, periph_clk_enb_refcnt);
+ clks[TEGRA124_CLK_DSIB] = clk;
/* emc mux */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
@@ -1351,7 +1349,7 @@ static const struct of_device_id pmc_match[] __initconst = {
{},
};
-static struct tegra_clk_init_table init_table[] __initdata = {
+static struct tegra_clk_init_table common_init_table[] __initdata = {
{TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0},
{TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0},
{TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0},
@@ -1368,6 +1366,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0},
{TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0},
{TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1},
+ {TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0},
+ {TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0},
{TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1},
{TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1},
{TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1},
@@ -1385,27 +1385,73 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
{TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
{TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
- {TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1},
{TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
{TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
{TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
+ /* This MUST be the last entry. */
+ {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
+};
+
+static struct tegra_clk_init_table tegra124_init_table[] __initdata = {
{TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0},
+ {TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1},
+ /* This MUST be the last entry. */
+ {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
+};
+
+/* Tegra132 requires the SOC_THERM clock to remain active */
+static struct tegra_clk_init_table tegra132_init_table[] __initdata = {
+ {TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 1},
/* This MUST be the last entry. */
{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
};
+/**
+ * tegra124_clock_apply_init_table - initialize clocks on Tegra124 SoCs
+ *
+ * Program an initial clock rate and enable or disable clocks needed
+ * by the rest of the kernel, for Tegra124 SoCs. It is intended to be
+ * called by assigning a pointer to it to tegra_clk_apply_init_table -
+ * this will be called as an arch_initcall. No return value.
+ */
static void __init tegra124_clock_apply_init_table(void)
{
- tegra_init_from_table(init_table, clks, TEGRA124_CLK_CLK_MAX);
+ tegra_init_from_table(common_init_table, clks, TEGRA124_CLK_CLK_MAX);
+ tegra_init_from_table(tegra124_init_table, clks, TEGRA124_CLK_CLK_MAX);
}
-static void __init tegra124_clock_init(struct device_node *np)
+/**
+ * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
+ *
+ * Program an initial clock rate and enable or disable clocks needed
+ * by the rest of the kernel, for Tegra132 SoCs. It is intended to be
+ * called by assigning a pointer to it to tegra_clk_apply_init_table -
+ * this will be called as an arch_initcall. No return value.
+ */
+static void __init tegra132_clock_apply_init_table(void)
+{
+ tegra_init_from_table(common_init_table, clks, TEGRA124_CLK_CLK_MAX);
+ tegra_init_from_table(tegra132_init_table, clks, TEGRA124_CLK_CLK_MAX);
+}
+
+/**
+ * tegra124_132_clock_init_pre - clock initialization preamble for T124/T132
+ * @np: struct device_node * of the DT node for the SoC CAR IP block
+ *
+ * Register most of the clocks controlled by the CAR IP block, along
+ * with a few clocks controlled by the PMC IP block. Everything in
+ * this function should be common to Tegra124 and Tegra132. XXX The
+ * PMC clock initialization should probably be moved to PMC-specific
+ * driver code. No return value.
+ */
+static void __init tegra124_132_clock_init_pre(struct device_node *np)
{
struct device_node *node;
+ u32 plld_base;
clk_base = of_iomap(np, 0);
if (!clk_base) {
- pr_err("ioremap tegra124 CAR failed\n");
+ pr_err("ioremap tegra124/tegra132 CAR failed\n");
return;
}
@@ -1423,7 +1469,8 @@ static void __init tegra124_clock_init(struct device_node *np)
return;
}
- clks = tegra_clk_init(clk_base, TEGRA124_CLK_CLK_MAX, 6);
+ clks = tegra_clk_init(clk_base, TEGRA124_CLK_CLK_MAX,
+ TEGRA124_CAR_BANK_COUNT);
if (!clks)
return;
@@ -1437,13 +1484,76 @@ static void __init tegra124_clock_init(struct device_node *np)
tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks, &pll_a_params);
tegra_pmc_clk_init(pmc_base, tegra124_clks);
+ /* For Tegra124 & Tegra132, PLLD is the only source for DSIA & DSIB */
+ plld_base = clk_readl(clk_base + PLLD_BASE);
+ plld_base &= ~BIT(25);
+ clk_writel(plld_base, clk_base + PLLD_BASE);
+}
+
+/**
+ * tegra124_132_clock_init_post - clock initialization postamble for T124/T132
+ * @np: struct device_node * of the DT node for the SoC CAR IP block
+ *
+ * Register most of the along with a few clocks controlled by the PMC
+ * IP block. Everything in this function should be common to Tegra124
+ * and Tegra132. This function must be called after
+ * tegra124_132_clock_init_pre(), otherwise clk_base and pmc_base will
+ * not be set. No return value.
+ */
+static void __init tegra124_132_clock_init_post(struct device_node *np)
+{
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
- &pll_x_params);
+ &pll_x_params);
tegra_add_of_provider(np);
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
+ tegra_cpu_car_ops = &tegra124_cpu_car_ops;
+}
+
+/**
+ * tegra124_clock_init - Tegra124-specific clock initialization
+ * @np: struct device_node * of the DT node for the SoC CAR IP block
+ *
+ * Register most SoC clocks for the Tegra124 system-on-chip. Most of
+ * this code is shared between the Tegra124 and Tegra132 SoCs,
+ * although some of the initial clock settings and CPU clocks differ.
+ * Intended to be called by the OF init code when a DT node with the
+ * "nvidia,tegra124-car" string is encountered, and declared with
+ * CLK_OF_DECLARE. No return value.
+ */
+static void __init tegra124_clock_init(struct device_node *np)
+{
+ tegra124_132_clock_init_pre(np);
tegra_clk_apply_init_table = tegra124_clock_apply_init_table;
+ tegra124_132_clock_init_post(np);
+}
- tegra_cpu_car_ops = &tegra124_cpu_car_ops;
+/**
+ * tegra132_clock_init - Tegra132-specific clock initialization
+ * @np: struct device_node * of the DT node for the SoC CAR IP block
+ *
+ * Register most SoC clocks for the Tegra132 system-on-chip. Most of
+ * this code is shared between the Tegra124 and Tegra132 SoCs,
+ * although some of the initial clock settings and CPU clocks differ.
+ * Intended to be called by the OF init code when a DT node with the
+ * "nvidia,tegra132-car" string is encountered, and declared with
+ * CLK_OF_DECLARE. No return value.
+ */
+static void __init tegra132_clock_init(struct device_node *np)
+{
+ tegra124_132_clock_init_pre(np);
+
+ /*
+ * On Tegra132, these clocks are controlled by the
+ * CLUSTER_clocks IP block, located in the CPU complex
+ */
+ tegra124_clks[tegra_clk_cclk_g].present = false;
+ tegra124_clks[tegra_clk_cclk_lp].present = false;
+ tegra124_clks[tegra_clk_pll_x].present = false;
+ tegra124_clks[tegra_clk_pll_x_out0].present = false;
+
+ tegra_clk_apply_init_table = tegra132_clock_apply_init_table;
+ tegra124_132_clock_init_post(np);
}
CLK_OF_DECLARE(tegra124, "nvidia,tegra124-car", tegra124_clock_init);
+CLK_OF_DECLARE(tegra132, "nvidia,tegra132-car", tegra132_clock_init);
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 97dc8595c3cd5c..9ddb7547cb431b 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -302,10 +302,13 @@ struct clk ** __init tegra_lookup_dt_id(int clk_id,
tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
-void __init tegra_clocks_apply_init_table(void)
+static int __init tegra_clocks_apply_init_table(void)
{
if (!tegra_clk_apply_init_table)
- return;
+ return 0;
tegra_clk_apply_init_table();
+
+ return 0;
}
+arch_initcall(tegra_clocks_apply_init_table);
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index ed4d0aaf891639..105ffd0f5e79da 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -1,13 +1,17 @@
-ifneq ($(CONFIG_OF),)
obj-y += clk.o autoidle.o clockdomain.o
clk-common = dpll.o composite.o divider.o gate.o \
fixed-factor.o mux.o apll.o
obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o
+obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-816x.o
obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
-obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o
+obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o \
+ clk-3xxx.o
obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o
obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o
obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \
clk-dra7-atl.o
obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o
+
+ifdef CONFIG_ATAGS
+obj-$(CONFIG_ARCH_OMAP3) += clk-3xxx-legacy.o
endif
diff --git a/drivers/clk/ti/clk-3xxx-legacy.c b/drivers/clk/ti/clk-3xxx-legacy.c
new file mode 100644
index 00000000000000..e0732a4c8f26b7
--- /dev/null
+++ b/drivers/clk/ti/clk-3xxx-legacy.c
@@ -0,0 +1,4653 @@
+/*
+ * OMAP3 Legacy clock data
+ *
+ * Copyright (C) 2014 Texas Instruments, Inc
+ * Tero Kristo (t-kristo@ti.com)
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+
+#include "clock.h"
+
+static struct ti_clk_fixed virt_12m_ck_data = {
+ .frequency = 12000000,
+};
+
+static struct ti_clk virt_12m_ck = {
+ .name = "virt_12m_ck",
+ .type = TI_CLK_FIXED,
+ .data = &virt_12m_ck_data,
+};
+
+static struct ti_clk_fixed virt_13m_ck_data = {
+ .frequency = 13000000,
+};
+
+static struct ti_clk virt_13m_ck = {
+ .name = "virt_13m_ck",
+ .type = TI_CLK_FIXED,
+ .data = &virt_13m_ck_data,
+};
+
+static struct ti_clk_fixed virt_19200000_ck_data = {
+ .frequency = 19200000,
+};
+
+static struct ti_clk virt_19200000_ck = {
+ .name = "virt_19200000_ck",
+ .type = TI_CLK_FIXED,
+ .data = &virt_19200000_ck_data,
+};
+
+static struct ti_clk_fixed virt_26000000_ck_data = {
+ .frequency = 26000000,
+};
+
+static struct ti_clk virt_26000000_ck = {
+ .name = "virt_26000000_ck",
+ .type = TI_CLK_FIXED,
+ .data = &virt_26000000_ck_data,
+};
+
+static struct ti_clk_fixed virt_38_4m_ck_data = {
+ .frequency = 38400000,
+};
+
+static struct ti_clk virt_38_4m_ck = {
+ .name = "virt_38_4m_ck",
+ .type = TI_CLK_FIXED,
+ .data = &virt_38_4m_ck_data,
+};
+
+static struct ti_clk_fixed virt_16_8m_ck_data = {
+ .frequency = 16800000,
+};
+
+static struct ti_clk virt_16_8m_ck = {
+ .name = "virt_16_8m_ck",
+ .type = TI_CLK_FIXED,
+ .data = &virt_16_8m_ck_data,
+};
+
+static const char *osc_sys_ck_parents[] = {
+ "virt_12m_ck",
+ "virt_13m_ck",
+ "virt_19200000_ck",
+ "virt_26000000_ck",
+ "virt_38_4m_ck",
+ "virt_16_8m_ck",
+};
+
+static struct ti_clk_mux osc_sys_ck_data = {
+ .num_parents = ARRAY_SIZE(osc_sys_ck_parents),
+ .reg = 0xd40,
+ .module = TI_CLKM_PRM,
+ .parents = osc_sys_ck_parents,
+};
+
+static struct ti_clk osc_sys_ck = {
+ .name = "osc_sys_ck",
+ .type = TI_CLK_MUX,
+ .data = &osc_sys_ck_data,
+};
+
+static struct ti_clk_divider sys_ck_data = {
+ .parent = "osc_sys_ck",
+ .bit_shift = 6,
+ .max_div = 3,
+ .reg = 0x1270,
+ .module = TI_CLKM_PRM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk sys_ck = {
+ .name = "sys_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &sys_ck_data,
+};
+
+static const char *dpll3_ck_parents[] = {
+ "sys_ck",
+ "sys_ck",
+};
+
+static struct ti_clk_dpll dpll3_ck_data = {
+ .num_parents = ARRAY_SIZE(dpll3_ck_parents),
+ .control_reg = 0xd00,
+ .idlest_reg = 0xd20,
+ .mult_div1_reg = 0xd40,
+ .autoidle_reg = 0xd30,
+ .module = TI_CLKM_CM,
+ .parents = dpll3_ck_parents,
+ .flags = CLKF_CORE,
+ .freqsel_mask = 0xf0,
+ .div1_mask = 0x7f00,
+ .idlest_mask = 0x1,
+ .auto_recal_bit = 0x3,
+ .max_divider = 0x80,
+ .min_divider = 0x1,
+ .recal_en_bit = 0x5,
+ .max_multiplier = 0x7ff,
+ .enable_mask = 0x7,
+ .mult_mask = 0x7ff0000,
+ .recal_st_bit = 0x5,
+ .autoidle_mask = 0x7,
+};
+
+static struct ti_clk dpll3_ck = {
+ .name = "dpll3_ck",
+ .clkdm_name = "dpll3_clkdm",
+ .type = TI_CLK_DPLL,
+ .data = &dpll3_ck_data,
+};
+
+static struct ti_clk_divider dpll3_m2_ck_data = {
+ .parent = "dpll3_ck",
+ .bit_shift = 27,
+ .max_div = 31,
+ .reg = 0xd40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll3_m2_ck = {
+ .name = "dpll3_m2_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll3_m2_ck_data,
+};
+
+static struct ti_clk_fixed_factor core_ck_data = {
+ .parent = "dpll3_m2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk core_ck = {
+ .name = "core_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_ck_data,
+};
+
+static struct ti_clk_divider l3_ick_data = {
+ .parent = "core_ck",
+ .max_div = 3,
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk l3_ick = {
+ .name = "l3_ick",
+ .type = TI_CLK_DIVIDER,
+ .data = &l3_ick_data,
+};
+
+static struct ti_clk_fixed_factor security_l3_ick_data = {
+ .parent = "l3_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk security_l3_ick = {
+ .name = "security_l3_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &security_l3_ick_data,
+};
+
+static struct ti_clk_fixed_factor wkup_l4_ick_data = {
+ .parent = "sys_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk wkup_l4_ick = {
+ .name = "wkup_l4_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &wkup_l4_ick_data,
+};
+
+static struct ti_clk_gate usim_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 9,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk usim_ick = {
+ .name = "usim_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &usim_ick_data,
+};
+
+static struct ti_clk_gate dss2_alwon_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 1,
+ .reg = 0xe00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk dss2_alwon_fck = {
+ .name = "dss2_alwon_fck",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss2_alwon_fck_data,
+};
+
+static struct ti_clk_divider l4_ick_data = {
+ .parent = "l3_ick",
+ .bit_shift = 2,
+ .max_div = 3,
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk l4_ick = {
+ .name = "l4_ick",
+ .type = TI_CLK_DIVIDER,
+ .data = &l4_ick_data,
+};
+
+static struct ti_clk_fixed_factor core_l4_ick_data = {
+ .parent = "l4_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk core_l4_ick = {
+ .name = "core_l4_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_l4_ick_data,
+};
+
+static struct ti_clk_gate mmchs2_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 25,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mmchs2_ick = {
+ .name = "mmchs2_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mmchs2_ick_data,
+};
+
+static const char *dpll4_ck_parents[] = {
+ "sys_ck",
+ "sys_ck",
+};
+
+static struct ti_clk_dpll dpll4_ck_data = {
+ .num_parents = ARRAY_SIZE(dpll4_ck_parents),
+ .control_reg = 0xd00,
+ .idlest_reg = 0xd20,
+ .mult_div1_reg = 0xd44,
+ .autoidle_reg = 0xd30,
+ .module = TI_CLKM_CM,
+ .parents = dpll4_ck_parents,
+ .flags = CLKF_PER,
+ .freqsel_mask = 0xf00000,
+ .modes = 0x82,
+ .div1_mask = 0x7f,
+ .idlest_mask = 0x2,
+ .auto_recal_bit = 0x13,
+ .max_divider = 0x80,
+ .min_divider = 0x1,
+ .recal_en_bit = 0x6,
+ .max_multiplier = 0x7ff,
+ .enable_mask = 0x70000,
+ .mult_mask = 0x7ff00,
+ .recal_st_bit = 0x6,
+ .autoidle_mask = 0x38,
+};
+
+static struct ti_clk dpll4_ck = {
+ .name = "dpll4_ck",
+ .clkdm_name = "dpll4_clkdm",
+ .type = TI_CLK_DPLL,
+ .data = &dpll4_ck_data,
+};
+
+static struct ti_clk_divider dpll4_m2_ck_data = {
+ .parent = "dpll4_ck",
+ .max_div = 63,
+ .reg = 0xd48,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll4_m2_ck = {
+ .name = "dpll4_m2_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll4_m2_ck_data,
+};
+
+static struct ti_clk_fixed_factor dpll4_m2x2_mul_ck_data = {
+ .parent = "dpll4_m2_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll4_m2x2_mul_ck = {
+ .name = "dpll4_m2x2_mul_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll4_m2x2_mul_ck_data,
+};
+
+static struct ti_clk_gate dpll4_m2x2_ck_data = {
+ .parent = "dpll4_m2x2_mul_ck",
+ .bit_shift = 0x1b,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m2x2_ck = {
+ .name = "dpll4_m2x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m2x2_ck_data,
+};
+
+static struct ti_clk_fixed_factor omap_96m_alwon_fck_data = {
+ .parent = "dpll4_m2x2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk omap_96m_alwon_fck = {
+ .name = "omap_96m_alwon_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_96m_alwon_fck_data,
+};
+
+static struct ti_clk_fixed_factor cm_96m_fck_data = {
+ .parent = "omap_96m_alwon_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk cm_96m_fck = {
+ .name = "cm_96m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &cm_96m_fck_data,
+};
+
+static const char *omap_96m_fck_parents[] = {
+ "cm_96m_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux omap_96m_fck_data = {
+ .bit_shift = 6,
+ .num_parents = ARRAY_SIZE(omap_96m_fck_parents),
+ .reg = 0xd40,
+ .module = TI_CLKM_CM,
+ .parents = omap_96m_fck_parents,
+};
+
+static struct ti_clk omap_96m_fck = {
+ .name = "omap_96m_fck",
+ .type = TI_CLK_MUX,
+ .data = &omap_96m_fck_data,
+};
+
+static struct ti_clk_fixed_factor core_96m_fck_data = {
+ .parent = "omap_96m_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk core_96m_fck = {
+ .name = "core_96m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_96m_fck_data,
+};
+
+static struct ti_clk_gate mspro_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 23,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mspro_fck = {
+ .name = "mspro_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mspro_fck_data,
+};
+
+static struct ti_clk_gate dss_ick_3430es2_data = {
+ .parent = "l4_ick",
+ .bit_shift = 0,
+ .reg = 0xe10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_DSS | CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk dss_ick_3430es2 = {
+ .name = "dss_ick",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss_ick_3430es2_data,
+};
+
+static struct ti_clk_gate uart4_ick_am35xx_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 23,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk uart4_ick_am35xx = {
+ .name = "uart4_ick_am35xx",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart4_ick_am35xx_data,
+};
+
+static struct ti_clk_fixed_factor security_l4_ick2_data = {
+ .parent = "l4_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk security_l4_ick2 = {
+ .name = "security_l4_ick2",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &security_l4_ick2_data,
+};
+
+static struct ti_clk_gate aes1_ick_data = {
+ .parent = "security_l4_ick2",
+ .bit_shift = 3,
+ .reg = 0xa14,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk aes1_ick = {
+ .name = "aes1_ick",
+ .type = TI_CLK_GATE,
+ .data = &aes1_ick_data,
+};
+
+static const char *dpll5_ck_parents[] = {
+ "sys_ck",
+ "sys_ck",
+};
+
+static struct ti_clk_dpll dpll5_ck_data = {
+ .num_parents = ARRAY_SIZE(dpll5_ck_parents),
+ .control_reg = 0xd04,
+ .idlest_reg = 0xd24,
+ .mult_div1_reg = 0xd4c,
+ .autoidle_reg = 0xd34,
+ .module = TI_CLKM_CM,
+ .parents = dpll5_ck_parents,
+ .freqsel_mask = 0xf0,
+ .modes = 0x82,
+ .div1_mask = 0x7f,
+ .idlest_mask = 0x1,
+ .auto_recal_bit = 0x3,
+ .max_divider = 0x80,
+ .min_divider = 0x1,
+ .recal_en_bit = 0x19,
+ .max_multiplier = 0x7ff,
+ .enable_mask = 0x7,
+ .mult_mask = 0x7ff00,
+ .recal_st_bit = 0x19,
+ .autoidle_mask = 0x7,
+};
+
+static struct ti_clk dpll5_ck = {
+ .name = "dpll5_ck",
+ .clkdm_name = "dpll5_clkdm",
+ .type = TI_CLK_DPLL,
+ .data = &dpll5_ck_data,
+};
+
+static struct ti_clk_divider dpll5_m2_ck_data = {
+ .parent = "dpll5_ck",
+ .max_div = 31,
+ .reg = 0xd50,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll5_m2_ck = {
+ .name = "dpll5_m2_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll5_m2_ck_data,
+};
+
+static struct ti_clk_gate usbhost_120m_fck_data = {
+ .parent = "dpll5_m2_ck",
+ .bit_shift = 1,
+ .reg = 0x1400,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk usbhost_120m_fck = {
+ .name = "usbhost_120m_fck",
+ .clkdm_name = "usbhost_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &usbhost_120m_fck_data,
+};
+
+static struct ti_clk_fixed_factor cm_96m_d2_fck_data = {
+ .parent = "cm_96m_fck",
+ .div = 2,
+ .mult = 1,
+};
+
+static struct ti_clk cm_96m_d2_fck = {
+ .name = "cm_96m_d2_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &cm_96m_d2_fck_data,
+};
+
+static struct ti_clk_fixed sys_altclk_data = {
+ .frequency = 0x0,
+};
+
+static struct ti_clk sys_altclk = {
+ .name = "sys_altclk",
+ .type = TI_CLK_FIXED,
+ .data = &sys_altclk_data,
+};
+
+static const char *omap_48m_fck_parents[] = {
+ "cm_96m_d2_fck",
+ "sys_altclk",
+};
+
+static struct ti_clk_mux omap_48m_fck_data = {
+ .bit_shift = 3,
+ .num_parents = ARRAY_SIZE(omap_48m_fck_parents),
+ .reg = 0xd40,
+ .module = TI_CLKM_CM,
+ .parents = omap_48m_fck_parents,
+};
+
+static struct ti_clk omap_48m_fck = {
+ .name = "omap_48m_fck",
+ .type = TI_CLK_MUX,
+ .data = &omap_48m_fck_data,
+};
+
+static struct ti_clk_fixed_factor core_48m_fck_data = {
+ .parent = "omap_48m_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk core_48m_fck = {
+ .name = "core_48m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_48m_fck_data,
+};
+
+static struct ti_clk_fixed mcbsp_clks_data = {
+ .frequency = 0x0,
+};
+
+static struct ti_clk mcbsp_clks = {
+ .name = "mcbsp_clks",
+ .type = TI_CLK_FIXED,
+ .data = &mcbsp_clks_data,
+};
+
+static struct ti_clk_gate mcbsp2_gate_fck_data = {
+ .parent = "mcbsp_clks",
+ .bit_shift = 0,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_fixed_factor per_96m_fck_data = {
+ .parent = "omap_96m_alwon_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk per_96m_fck = {
+ .name = "per_96m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &per_96m_fck_data,
+};
+
+static const char *mcbsp2_mux_fck_parents[] = {
+ "per_96m_fck",
+ "mcbsp_clks",
+};
+
+static struct ti_clk_mux mcbsp2_mux_fck_data = {
+ .bit_shift = 6,
+ .num_parents = ARRAY_SIZE(mcbsp2_mux_fck_parents),
+ .reg = 0x274,
+ .module = TI_CLKM_SCRM,
+ .parents = mcbsp2_mux_fck_parents,
+};
+
+static struct ti_clk_composite mcbsp2_fck_data = {
+ .mux = &mcbsp2_mux_fck_data,
+ .gate = &mcbsp2_gate_fck_data,
+};
+
+static struct ti_clk mcbsp2_fck = {
+ .name = "mcbsp2_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &mcbsp2_fck_data,
+};
+
+static struct ti_clk_fixed_factor dpll3_m2x2_ck_data = {
+ .parent = "dpll3_m2_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll3_m2x2_ck = {
+ .name = "dpll3_m2x2_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll3_m2x2_ck_data,
+};
+
+static struct ti_clk_fixed_factor corex2_fck_data = {
+ .parent = "dpll3_m2x2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk corex2_fck = {
+ .name = "corex2_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &corex2_fck_data,
+};
+
+static struct ti_clk_gate ssi_ssr_gate_fck_3430es1_data = {
+ .parent = "corex2_fck",
+ .bit_shift = 0,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_NO_WAIT,
+};
+
+static int ssi_ssr_div_fck_3430es1_divs[] = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 0,
+ 6,
+ 0,
+ 8,
+};
+
+static struct ti_clk_divider ssi_ssr_div_fck_3430es1_data = {
+ .num_dividers = ARRAY_SIZE(ssi_ssr_div_fck_3430es1_divs),
+ .parent = "corex2_fck",
+ .bit_shift = 8,
+ .dividers = ssi_ssr_div_fck_3430es1_divs,
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_composite ssi_ssr_fck_3430es1_data = {
+ .gate = &ssi_ssr_gate_fck_3430es1_data,
+ .divider = &ssi_ssr_div_fck_3430es1_data,
+};
+
+static struct ti_clk ssi_ssr_fck_3430es1 = {
+ .name = "ssi_ssr_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &ssi_ssr_fck_3430es1_data,
+};
+
+static struct ti_clk_fixed_factor ssi_sst_fck_3430es1_data = {
+ .parent = "ssi_ssr_fck",
+ .div = 2,
+ .mult = 1,
+};
+
+static struct ti_clk ssi_sst_fck_3430es1 = {
+ .name = "ssi_sst_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &ssi_sst_fck_3430es1_data,
+};
+
+static struct ti_clk_fixed omap_32k_fck_data = {
+ .frequency = 32768,
+};
+
+static struct ti_clk omap_32k_fck = {
+ .name = "omap_32k_fck",
+ .type = TI_CLK_FIXED,
+ .data = &omap_32k_fck_data,
+};
+
+static struct ti_clk_fixed_factor per_32k_alwon_fck_data = {
+ .parent = "omap_32k_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk per_32k_alwon_fck = {
+ .name = "per_32k_alwon_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &per_32k_alwon_fck_data,
+};
+
+static struct ti_clk_gate gpio5_dbck_data = {
+ .parent = "per_32k_alwon_fck",
+ .bit_shift = 16,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk gpio5_dbck = {
+ .name = "gpio5_dbck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio5_dbck_data,
+};
+
+static struct ti_clk_gate gpt1_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 0,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt1_ick = {
+ .name = "gpt1_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt1_ick_data,
+};
+
+static struct ti_clk_gate mcspi3_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 20,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mcspi3_fck = {
+ .name = "mcspi3_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi3_fck_data,
+};
+
+static struct ti_clk_gate gpt2_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 3,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static const char *gpt2_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt2_mux_fck_data = {
+ .num_parents = ARRAY_SIZE(gpt2_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt2_mux_fck_parents,
+};
+
+static struct ti_clk_composite gpt2_fck_data = {
+ .mux = &gpt2_mux_fck_data,
+ .gate = &gpt2_gate_fck_data,
+};
+
+static struct ti_clk gpt2_fck = {
+ .name = "gpt2_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt2_fck_data,
+};
+
+static struct ti_clk_gate gpt10_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 11,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt10_ick = {
+ .name = "gpt10_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt10_ick_data,
+};
+
+static struct ti_clk_gate uart2_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 14,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk uart2_fck = {
+ .name = "uart2_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart2_fck_data,
+};
+
+static struct ti_clk_fixed_factor sr_l4_ick_data = {
+ .parent = "l4_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk sr_l4_ick = {
+ .name = "sr_l4_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &sr_l4_ick_data,
+};
+
+static struct ti_clk_fixed_factor omap_96m_d8_fck_data = {
+ .parent = "omap_96m_fck",
+ .div = 8,
+ .mult = 1,
+};
+
+static struct ti_clk omap_96m_d8_fck = {
+ .name = "omap_96m_d8_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_96m_d8_fck_data,
+};
+
+static struct ti_clk_divider dpll4_m5_ck_data = {
+ .parent = "dpll4_ck",
+ .max_div = 63,
+ .reg = 0xf40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll4_m5_ck = {
+ .name = "dpll4_m5_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll4_m5_ck_data,
+};
+
+static struct ti_clk_fixed_factor dpll4_m5x2_mul_ck_data = {
+ .parent = "dpll4_m5_ck",
+ .div = 1,
+ .mult = 2,
+ .flags = CLKF_SET_RATE_PARENT,
+};
+
+static struct ti_clk dpll4_m5x2_mul_ck = {
+ .name = "dpll4_m5x2_mul_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll4_m5x2_mul_ck_data,
+};
+
+static struct ti_clk_gate dpll4_m5x2_ck_data = {
+ .parent = "dpll4_m5x2_mul_ck",
+ .bit_shift = 0x1e,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m5x2_ck = {
+ .name = "dpll4_m5x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m5x2_ck_data,
+};
+
+static struct ti_clk_gate cam_mclk_data = {
+ .parent = "dpll4_m5x2_ck",
+ .bit_shift = 0,
+ .reg = 0xf00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_RATE_PARENT,
+};
+
+static struct ti_clk cam_mclk = {
+ .name = "cam_mclk",
+ .type = TI_CLK_GATE,
+ .data = &cam_mclk_data,
+};
+
+static struct ti_clk_gate mcbsp3_gate_fck_data = {
+ .parent = "mcbsp_clks",
+ .bit_shift = 1,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static const char *mcbsp3_mux_fck_parents[] = {
+ "per_96m_fck",
+ "mcbsp_clks",
+};
+
+static struct ti_clk_mux mcbsp3_mux_fck_data = {
+ .num_parents = ARRAY_SIZE(mcbsp3_mux_fck_parents),
+ .reg = 0x2d8,
+ .module = TI_CLKM_SCRM,
+ .parents = mcbsp3_mux_fck_parents,
+};
+
+static struct ti_clk_composite mcbsp3_fck_data = {
+ .mux = &mcbsp3_mux_fck_data,
+ .gate = &mcbsp3_gate_fck_data,
+};
+
+static struct ti_clk mcbsp3_fck = {
+ .name = "mcbsp3_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &mcbsp3_fck_data,
+};
+
+static struct ti_clk_gate csi2_96m_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 1,
+ .reg = 0xf00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk csi2_96m_fck = {
+ .name = "csi2_96m_fck",
+ .clkdm_name = "cam_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &csi2_96m_fck_data,
+};
+
+static struct ti_clk_gate gpt9_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 10,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static const char *gpt9_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt9_mux_fck_data = {
+ .bit_shift = 7,
+ .num_parents = ARRAY_SIZE(gpt9_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt9_mux_fck_parents,
+};
+
+static struct ti_clk_composite gpt9_fck_data = {
+ .mux = &gpt9_mux_fck_data,
+ .gate = &gpt9_gate_fck_data,
+};
+
+static struct ti_clk gpt9_fck = {
+ .name = "gpt9_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt9_fck_data,
+};
+
+static struct ti_clk_divider dpll3_m3_ck_data = {
+ .parent = "dpll3_ck",
+ .bit_shift = 16,
+ .max_div = 31,
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll3_m3_ck = {
+ .name = "dpll3_m3_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll3_m3_ck_data,
+};
+
+static struct ti_clk_fixed_factor dpll3_m3x2_mul_ck_data = {
+ .parent = "dpll3_m3_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll3_m3x2_mul_ck = {
+ .name = "dpll3_m3x2_mul_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll3_m3x2_mul_ck_data,
+};
+
+static struct ti_clk_gate sr2_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 7,
+ .reg = 0xc00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk sr2_fck = {
+ .name = "sr2_fck",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &sr2_fck_data,
+};
+
+static struct ti_clk_fixed pclk_ck_data = {
+ .frequency = 27000000,
+};
+
+static struct ti_clk pclk_ck = {
+ .name = "pclk_ck",
+ .type = TI_CLK_FIXED,
+ .data = &pclk_ck_data,
+};
+
+static struct ti_clk_gate wdt2_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 5,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk wdt2_ick = {
+ .name = "wdt2_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &wdt2_ick_data,
+};
+
+static struct ti_clk_fixed_factor core_l3_ick_data = {
+ .parent = "l3_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk core_l3_ick = {
+ .name = "core_l3_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_l3_ick_data,
+};
+
+static struct ti_clk_gate mcspi4_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 21,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mcspi4_fck = {
+ .name = "mcspi4_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi4_fck_data,
+};
+
+static struct ti_clk_fixed_factor per_48m_fck_data = {
+ .parent = "omap_48m_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk per_48m_fck = {
+ .name = "per_48m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &per_48m_fck_data,
+};
+
+static struct ti_clk_gate uart4_fck_data = {
+ .parent = "per_48m_fck",
+ .bit_shift = 18,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk uart4_fck = {
+ .name = "uart4_fck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart4_fck_data,
+};
+
+static struct ti_clk_fixed_factor omap_96m_d10_fck_data = {
+ .parent = "omap_96m_fck",
+ .div = 10,
+ .mult = 1,
+};
+
+static struct ti_clk omap_96m_d10_fck = {
+ .name = "omap_96m_d10_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_96m_d10_fck_data,
+};
+
+static struct ti_clk_gate usim_gate_fck_data = {
+ .parent = "omap_96m_fck",
+ .bit_shift = 9,
+ .reg = 0xc00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_fixed_factor per_l4_ick_data = {
+ .parent = "l4_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk per_l4_ick = {
+ .name = "per_l4_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &per_l4_ick_data,
+};
+
+static struct ti_clk_gate gpt5_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 6,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt5_ick = {
+ .name = "gpt5_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt5_ick_data,
+};
+
+static struct ti_clk_gate mcspi2_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 19,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcspi2_ick = {
+ .name = "mcspi2_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi2_ick_data,
+};
+
+static struct ti_clk_fixed_factor ssi_l4_ick_data = {
+ .parent = "l4_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk ssi_l4_ick = {
+ .name = "ssi_l4_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &ssi_l4_ick_data,
+};
+
+static struct ti_clk_gate ssi_ick_3430es1_data = {
+ .parent = "ssi_l4_ick",
+ .bit_shift = 0,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_NO_WAIT | CLKF_INTERFACE,
+};
+
+static struct ti_clk ssi_ick_3430es1 = {
+ .name = "ssi_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &ssi_ick_3430es1_data,
+};
+
+static struct ti_clk_gate i2c2_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 16,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk i2c2_fck = {
+ .name = "i2c2_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &i2c2_fck_data,
+};
+
+static struct ti_clk_divider dpll1_fck_data = {
+ .parent = "core_ck",
+ .bit_shift = 19,
+ .max_div = 7,
+ .reg = 0x940,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll1_fck = {
+ .name = "dpll1_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll1_fck_data,
+};
+
+static const char *dpll1_ck_parents[] = {
+ "sys_ck",
+ "dpll1_fck",
+};
+
+static struct ti_clk_dpll dpll1_ck_data = {
+ .num_parents = ARRAY_SIZE(dpll1_ck_parents),
+ .control_reg = 0x904,
+ .idlest_reg = 0x924,
+ .mult_div1_reg = 0x940,
+ .autoidle_reg = 0x934,
+ .module = TI_CLKM_CM,
+ .parents = dpll1_ck_parents,
+ .freqsel_mask = 0xf0,
+ .modes = 0xa0,
+ .div1_mask = 0x7f,
+ .idlest_mask = 0x1,
+ .auto_recal_bit = 0x3,
+ .max_divider = 0x80,
+ .min_divider = 0x1,
+ .recal_en_bit = 0x7,
+ .max_multiplier = 0x7ff,
+ .enable_mask = 0x7,
+ .mult_mask = 0x7ff00,
+ .recal_st_bit = 0x7,
+ .autoidle_mask = 0x7,
+};
+
+static struct ti_clk dpll1_ck = {
+ .name = "dpll1_ck",
+ .clkdm_name = "dpll1_clkdm",
+ .type = TI_CLK_DPLL,
+ .data = &dpll1_ck_data,
+};
+
+static struct ti_clk_fixed secure_32k_fck_data = {
+ .frequency = 32768,
+};
+
+static struct ti_clk secure_32k_fck = {
+ .name = "secure_32k_fck",
+ .type = TI_CLK_FIXED,
+ .data = &secure_32k_fck_data,
+};
+
+static struct ti_clk_gate gpio5_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 16,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpio5_ick = {
+ .name = "gpio5_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio5_ick_data,
+};
+
+static struct ti_clk_divider dpll4_m4_ck_data = {
+ .parent = "dpll4_ck",
+ .max_div = 32,
+ .reg = 0xe40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll4_m4_ck = {
+ .name = "dpll4_m4_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll4_m4_ck_data,
+};
+
+static struct ti_clk_fixed_factor dpll4_m4x2_mul_ck_data = {
+ .parent = "dpll4_m4_ck",
+ .div = 1,
+ .mult = 2,
+ .flags = CLKF_SET_RATE_PARENT,
+};
+
+static struct ti_clk dpll4_m4x2_mul_ck = {
+ .name = "dpll4_m4x2_mul_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll4_m4x2_mul_ck_data,
+};
+
+static struct ti_clk_gate dpll4_m4x2_ck_data = {
+ .parent = "dpll4_m4x2_mul_ck",
+ .bit_shift = 0x1d,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_RATE_PARENT | CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m4x2_ck = {
+ .name = "dpll4_m4x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m4x2_ck_data,
+};
+
+static struct ti_clk_gate dss1_alwon_fck_3430es2_data = {
+ .parent = "dpll4_m4x2_ck",
+ .bit_shift = 0,
+ .reg = 0xe00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_DSS | CLKF_SET_RATE_PARENT,
+};
+
+static struct ti_clk dss1_alwon_fck_3430es2 = {
+ .name = "dss1_alwon_fck",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss1_alwon_fck_3430es2_data,
+};
+
+static struct ti_clk_gate uart3_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 11,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk uart3_ick = {
+ .name = "uart3_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart3_ick_data,
+};
+
+static struct ti_clk_divider dpll4_m3_ck_data = {
+ .parent = "dpll4_ck",
+ .bit_shift = 8,
+ .max_div = 32,
+ .reg = 0xe40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll4_m3_ck = {
+ .name = "dpll4_m3_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll4_m3_ck_data,
+};
+
+static struct ti_clk_gate mcbsp3_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 1,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcbsp3_ick = {
+ .name = "mcbsp3_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcbsp3_ick_data,
+};
+
+static struct ti_clk_gate gpio3_dbck_data = {
+ .parent = "per_32k_alwon_fck",
+ .bit_shift = 14,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk gpio3_dbck = {
+ .name = "gpio3_dbck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio3_dbck_data,
+};
+
+static struct ti_clk_gate fac_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 8,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk fac_ick = {
+ .name = "fac_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &fac_ick_data,
+};
+
+static struct ti_clk_gate clkout2_src_gate_ck_data = {
+ .parent = "core_ck",
+ .bit_shift = 7,
+ .reg = 0xd70,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_NO_WAIT,
+};
+
+static struct ti_clk_fixed_factor dpll4_m3x2_mul_ck_data = {
+ .parent = "dpll4_m3_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll4_m3x2_mul_ck = {
+ .name = "dpll4_m3x2_mul_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll4_m3x2_mul_ck_data,
+};
+
+static struct ti_clk_gate dpll4_m3x2_ck_data = {
+ .parent = "dpll4_m3x2_mul_ck",
+ .bit_shift = 0x1c,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m3x2_ck = {
+ .name = "dpll4_m3x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m3x2_ck_data,
+};
+
+static const char *omap_54m_fck_parents[] = {
+ "dpll4_m3x2_ck",
+ "sys_altclk",
+};
+
+static struct ti_clk_mux omap_54m_fck_data = {
+ .bit_shift = 5,
+ .num_parents = ARRAY_SIZE(omap_54m_fck_parents),
+ .reg = 0xd40,
+ .module = TI_CLKM_CM,
+ .parents = omap_54m_fck_parents,
+};
+
+static struct ti_clk omap_54m_fck = {
+ .name = "omap_54m_fck",
+ .type = TI_CLK_MUX,
+ .data = &omap_54m_fck_data,
+};
+
+static const char *clkout2_src_mux_ck_parents[] = {
+ "core_ck",
+ "sys_ck",
+ "cm_96m_fck",
+ "omap_54m_fck",
+};
+
+static struct ti_clk_mux clkout2_src_mux_ck_data = {
+ .num_parents = ARRAY_SIZE(clkout2_src_mux_ck_parents),
+ .reg = 0xd70,
+ .module = TI_CLKM_CM,
+ .parents = clkout2_src_mux_ck_parents,
+};
+
+static struct ti_clk_composite clkout2_src_ck_data = {
+ .mux = &clkout2_src_mux_ck_data,
+ .gate = &clkout2_src_gate_ck_data,
+};
+
+static struct ti_clk clkout2_src_ck = {
+ .name = "clkout2_src_ck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &clkout2_src_ck_data,
+};
+
+static struct ti_clk_gate i2c1_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 15,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk i2c1_fck = {
+ .name = "i2c1_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &i2c1_fck_data,
+};
+
+static struct ti_clk_gate wdt3_fck_data = {
+ .parent = "per_32k_alwon_fck",
+ .bit_shift = 12,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk wdt3_fck = {
+ .name = "wdt3_fck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &wdt3_fck_data,
+};
+
+static struct ti_clk_gate gpt7_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 8,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static const char *gpt7_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt7_mux_fck_data = {
+ .bit_shift = 5,
+ .num_parents = ARRAY_SIZE(gpt7_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt7_mux_fck_parents,
+};
+
+static struct ti_clk_composite gpt7_fck_data = {
+ .mux = &gpt7_mux_fck_data,
+ .gate = &gpt7_gate_fck_data,
+};
+
+static struct ti_clk gpt7_fck = {
+ .name = "gpt7_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt7_fck_data,
+};
+
+static struct ti_clk_gate usb_l4_gate_ick_data = {
+ .parent = "l4_ick",
+ .bit_shift = 5,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INTERFACE,
+};
+
+static struct ti_clk_divider usb_l4_div_ick_data = {
+ .parent = "l4_ick",
+ .bit_shift = 4,
+ .max_div = 1,
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk_composite usb_l4_ick_data = {
+ .gate = &usb_l4_gate_ick_data,
+ .divider = &usb_l4_div_ick_data,
+};
+
+static struct ti_clk usb_l4_ick = {
+ .name = "usb_l4_ick",
+ .type = TI_CLK_COMPOSITE,
+ .data = &usb_l4_ick_data,
+};
+
+static struct ti_clk_gate uart4_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 18,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk uart4_ick = {
+ .name = "uart4_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart4_ick_data,
+};
+
+static struct ti_clk_fixed dummy_ck_data = {
+ .frequency = 0,
+};
+
+static struct ti_clk dummy_ck = {
+ .name = "dummy_ck",
+ .type = TI_CLK_FIXED,
+ .data = &dummy_ck_data,
+};
+
+static const char *gpt3_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt3_mux_fck_data = {
+ .bit_shift = 1,
+ .num_parents = ARRAY_SIZE(gpt3_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt3_mux_fck_parents,
+};
+
+static struct ti_clk_gate gpt9_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 10,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt9_ick = {
+ .name = "gpt9_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt9_ick_data,
+};
+
+static struct ti_clk_gate gpt10_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 11,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_gate dss_ick_3430es1_data = {
+ .parent = "l4_ick",
+ .bit_shift = 0,
+ .reg = 0xe10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_NO_WAIT | CLKF_INTERFACE,
+};
+
+static struct ti_clk dss_ick_3430es1 = {
+ .name = "dss_ick",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss_ick_3430es1_data,
+};
+
+static struct ti_clk_gate gpt11_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 12,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt11_ick = {
+ .name = "gpt11_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt11_ick_data,
+};
+
+static struct ti_clk_divider dpll2_fck_data = {
+ .parent = "core_ck",
+ .bit_shift = 19,
+ .max_div = 7,
+ .reg = 0x40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll2_fck = {
+ .name = "dpll2_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll2_fck_data,
+};
+
+static struct ti_clk_gate uart1_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 13,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk uart1_fck = {
+ .name = "uart1_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart1_fck_data,
+};
+
+static struct ti_clk_gate hsotgusb_ick_3430es1_data = {
+ .parent = "core_l3_ick",
+ .bit_shift = 4,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_NO_WAIT | CLKF_INTERFACE,
+};
+
+static struct ti_clk hsotgusb_ick_3430es1 = {
+ .name = "hsotgusb_ick_3430es1",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hsotgusb_ick_3430es1_data,
+};
+
+static struct ti_clk_gate gpio2_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 13,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpio2_ick = {
+ .name = "gpio2_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio2_ick_data,
+};
+
+static struct ti_clk_gate mmchs1_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 24,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mmchs1_ick = {
+ .name = "mmchs1_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mmchs1_ick_data,
+};
+
+static struct ti_clk_gate modem_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 31,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk modem_fck = {
+ .name = "modem_fck",
+ .clkdm_name = "d2d_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &modem_fck_data,
+};
+
+static struct ti_clk_gate mcbsp4_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 2,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcbsp4_ick = {
+ .name = "mcbsp4_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcbsp4_ick_data,
+};
+
+static struct ti_clk_gate gpio1_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 3,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpio1_ick = {
+ .name = "gpio1_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio1_ick_data,
+};
+
+static const char *gpt6_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt6_mux_fck_data = {
+ .bit_shift = 4,
+ .num_parents = ARRAY_SIZE(gpt6_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt6_mux_fck_parents,
+};
+
+static struct ti_clk_fixed_factor dpll1_x2_ck_data = {
+ .parent = "dpll1_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll1_x2_ck = {
+ .name = "dpll1_x2_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll1_x2_ck_data,
+};
+
+static struct ti_clk_divider dpll1_x2m2_ck_data = {
+ .parent = "dpll1_x2_ck",
+ .max_div = 31,
+ .reg = 0x944,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll1_x2m2_ck = {
+ .name = "dpll1_x2m2_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll1_x2m2_ck_data,
+};
+
+static struct ti_clk_fixed_factor mpu_ck_data = {
+ .parent = "dpll1_x2m2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk mpu_ck = {
+ .name = "mpu_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &mpu_ck_data,
+};
+
+static struct ti_clk_divider arm_fck_data = {
+ .parent = "mpu_ck",
+ .max_div = 2,
+ .reg = 0x924,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk arm_fck = {
+ .name = "arm_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &arm_fck_data,
+};
+
+static struct ti_clk_fixed_factor core_d3_ck_data = {
+ .parent = "core_ck",
+ .div = 3,
+ .mult = 1,
+};
+
+static struct ti_clk core_d3_ck = {
+ .name = "core_d3_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_d3_ck_data,
+};
+
+static struct ti_clk_gate gpt11_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 12,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+};
+
+static const char *gpt11_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt11_mux_fck_data = {
+ .bit_shift = 7,
+ .num_parents = ARRAY_SIZE(gpt11_mux_fck_parents),
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+ .parents = gpt11_mux_fck_parents,
+};
+
+static struct ti_clk_composite gpt11_fck_data = {
+ .mux = &gpt11_mux_fck_data,
+ .gate = &gpt11_gate_fck_data,
+};
+
+static struct ti_clk gpt11_fck = {
+ .name = "gpt11_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt11_fck_data,
+};
+
+static struct ti_clk_fixed_factor core_d6_ck_data = {
+ .parent = "core_ck",
+ .div = 6,
+ .mult = 1,
+};
+
+static struct ti_clk core_d6_ck = {
+ .name = "core_d6_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_d6_ck_data,
+};
+
+static struct ti_clk_gate uart4_fck_am35xx_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 23,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk uart4_fck_am35xx = {
+ .name = "uart4_fck_am35xx",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart4_fck_am35xx_data,
+};
+
+static struct ti_clk_gate dpll3_m3x2_ck_data = {
+ .parent = "dpll3_m3x2_mul_ck",
+ .bit_shift = 0xc,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll3_m3x2_ck = {
+ .name = "dpll3_m3x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll3_m3x2_ck_data,
+};
+
+static struct ti_clk_fixed_factor emu_core_alwon_ck_data = {
+ .parent = "dpll3_m3x2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk emu_core_alwon_ck = {
+ .name = "emu_core_alwon_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &emu_core_alwon_ck_data,
+};
+
+static struct ti_clk_divider dpll4_m6_ck_data = {
+ .parent = "dpll4_ck",
+ .bit_shift = 24,
+ .max_div = 63,
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll4_m6_ck = {
+ .name = "dpll4_m6_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll4_m6_ck_data,
+};
+
+static struct ti_clk_fixed_factor dpll4_m6x2_mul_ck_data = {
+ .parent = "dpll4_m6_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll4_m6x2_mul_ck = {
+ .name = "dpll4_m6x2_mul_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll4_m6x2_mul_ck_data,
+};
+
+static struct ti_clk_gate dpll4_m6x2_ck_data = {
+ .parent = "dpll4_m6x2_mul_ck",
+ .bit_shift = 0x1f,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m6x2_ck = {
+ .name = "dpll4_m6x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m6x2_ck_data,
+};
+
+static struct ti_clk_fixed_factor emu_per_alwon_ck_data = {
+ .parent = "dpll4_m6x2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk emu_per_alwon_ck = {
+ .name = "emu_per_alwon_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &emu_per_alwon_ck_data,
+};
+
+static struct ti_clk_fixed_factor emu_mpu_alwon_ck_data = {
+ .parent = "mpu_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk emu_mpu_alwon_ck = {
+ .name = "emu_mpu_alwon_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &emu_mpu_alwon_ck_data,
+};
+
+static const char *emu_src_mux_ck_parents[] = {
+ "sys_ck",
+ "emu_core_alwon_ck",
+ "emu_per_alwon_ck",
+ "emu_mpu_alwon_ck",
+};
+
+static struct ti_clk_mux emu_src_mux_ck_data = {
+ .num_parents = ARRAY_SIZE(emu_src_mux_ck_parents),
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .parents = emu_src_mux_ck_parents,
+};
+
+static struct ti_clk emu_src_mux_ck = {
+ .name = "emu_src_mux_ck",
+ .type = TI_CLK_MUX,
+ .data = &emu_src_mux_ck_data,
+};
+
+static struct ti_clk_gate emu_src_ck_data = {
+ .parent = "emu_src_mux_ck",
+ .flags = CLKF_CLKDM,
+};
+
+static struct ti_clk emu_src_ck = {
+ .name = "emu_src_ck",
+ .clkdm_name = "emu_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &emu_src_ck_data,
+};
+
+static struct ti_clk_divider atclk_fck_data = {
+ .parent = "emu_src_ck",
+ .bit_shift = 4,
+ .max_div = 3,
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk atclk_fck = {
+ .name = "atclk_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &atclk_fck_data,
+};
+
+static struct ti_clk_gate ipss_ick_data = {
+ .parent = "core_l3_ick",
+ .bit_shift = 4,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_AM35XX | CLKF_INTERFACE,
+};
+
+static struct ti_clk ipss_ick = {
+ .name = "ipss_ick",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &ipss_ick_data,
+};
+
+static struct ti_clk_gate emac_ick_data = {
+ .parent = "ipss_ick",
+ .bit_shift = 1,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+ .flags = CLKF_AM35XX,
+};
+
+static struct ti_clk emac_ick = {
+ .name = "emac_ick",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &emac_ick_data,
+};
+
+static struct ti_clk_gate vpfe_ick_data = {
+ .parent = "ipss_ick",
+ .bit_shift = 2,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+ .flags = CLKF_AM35XX,
+};
+
+static struct ti_clk vpfe_ick = {
+ .name = "vpfe_ick",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &vpfe_ick_data,
+};
+
+static const char *dpll2_ck_parents[] = {
+ "sys_ck",
+ "dpll2_fck",
+};
+
+static struct ti_clk_dpll dpll2_ck_data = {
+ .num_parents = ARRAY_SIZE(dpll2_ck_parents),
+ .control_reg = 0x4,
+ .idlest_reg = 0x24,
+ .mult_div1_reg = 0x40,
+ .autoidle_reg = 0x34,
+ .module = TI_CLKM_CM,
+ .parents = dpll2_ck_parents,
+ .freqsel_mask = 0xf0,
+ .modes = 0xa2,
+ .div1_mask = 0x7f,
+ .idlest_mask = 0x1,
+ .auto_recal_bit = 0x3,
+ .max_divider = 0x80,
+ .min_divider = 0x1,
+ .recal_en_bit = 0x8,
+ .max_multiplier = 0x7ff,
+ .enable_mask = 0x7,
+ .mult_mask = 0x7ff00,
+ .recal_st_bit = 0x8,
+ .autoidle_mask = 0x7,
+};
+
+static struct ti_clk dpll2_ck = {
+ .name = "dpll2_ck",
+ .clkdm_name = "dpll2_clkdm",
+ .type = TI_CLK_DPLL,
+ .data = &dpll2_ck_data,
+};
+
+static struct ti_clk_divider dpll2_m2_ck_data = {
+ .parent = "dpll2_ck",
+ .max_div = 31,
+ .reg = 0x44,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk dpll2_m2_ck = {
+ .name = "dpll2_m2_ck",
+ .type = TI_CLK_DIVIDER,
+ .data = &dpll2_m2_ck_data,
+};
+
+static const char *mcbsp4_mux_fck_parents[] = {
+ "per_96m_fck",
+ "mcbsp_clks",
+};
+
+static struct ti_clk_mux mcbsp4_mux_fck_data = {
+ .bit_shift = 2,
+ .num_parents = ARRAY_SIZE(mcbsp4_mux_fck_parents),
+ .reg = 0x2d8,
+ .module = TI_CLKM_SCRM,
+ .parents = mcbsp4_mux_fck_parents,
+};
+
+static const char *mcbsp1_mux_fck_parents[] = {
+ "core_96m_fck",
+ "mcbsp_clks",
+};
+
+static struct ti_clk_mux mcbsp1_mux_fck_data = {
+ .bit_shift = 2,
+ .num_parents = ARRAY_SIZE(mcbsp1_mux_fck_parents),
+ .reg = 0x274,
+ .module = TI_CLKM_SCRM,
+ .parents = mcbsp1_mux_fck_parents,
+};
+
+static struct ti_clk_gate gpt8_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 9,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_gate gpt8_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 9,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt8_ick = {
+ .name = "gpt8_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt8_ick_data,
+};
+
+static const char *gpt10_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt10_mux_fck_data = {
+ .bit_shift = 6,
+ .num_parents = ARRAY_SIZE(gpt10_mux_fck_parents),
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+ .parents = gpt10_mux_fck_parents,
+};
+
+static struct ti_clk_gate mmchs3_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 30,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mmchs3_ick = {
+ .name = "mmchs3_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mmchs3_ick_data,
+};
+
+static struct ti_clk_gate gpio3_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 14,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpio3_ick = {
+ .name = "gpio3_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio3_ick_data,
+};
+
+static const char *traceclk_src_fck_parents[] = {
+ "sys_ck",
+ "emu_core_alwon_ck",
+ "emu_per_alwon_ck",
+ "emu_mpu_alwon_ck",
+};
+
+static struct ti_clk_mux traceclk_src_fck_data = {
+ .bit_shift = 2,
+ .num_parents = ARRAY_SIZE(traceclk_src_fck_parents),
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .parents = traceclk_src_fck_parents,
+};
+
+static struct ti_clk traceclk_src_fck = {
+ .name = "traceclk_src_fck",
+ .type = TI_CLK_MUX,
+ .data = &traceclk_src_fck_data,
+};
+
+static struct ti_clk_divider traceclk_fck_data = {
+ .parent = "traceclk_src_fck",
+ .bit_shift = 11,
+ .max_div = 7,
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk traceclk_fck = {
+ .name = "traceclk_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &traceclk_fck_data,
+};
+
+static struct ti_clk_gate mcbsp5_gate_fck_data = {
+ .parent = "mcbsp_clks",
+ .bit_shift = 10,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_gate sad2d_ick_data = {
+ .parent = "l3_ick",
+ .bit_shift = 3,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk sad2d_ick = {
+ .name = "sad2d_ick",
+ .clkdm_name = "d2d_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &sad2d_ick_data,
+};
+
+static const char *gpt1_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt1_mux_fck_data = {
+ .num_parents = ARRAY_SIZE(gpt1_mux_fck_parents),
+ .reg = 0xc40,
+ .module = TI_CLKM_CM,
+ .parents = gpt1_mux_fck_parents,
+};
+
+static struct ti_clk_gate hecc_ck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 3,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+ .flags = CLKF_AM35XX,
+};
+
+static struct ti_clk hecc_ck = {
+ .name = "hecc_ck",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hecc_ck_data,
+};
+
+static struct ti_clk_gate gpt1_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 0,
+ .reg = 0xc00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_composite gpt1_fck_data = {
+ .mux = &gpt1_mux_fck_data,
+ .gate = &gpt1_gate_fck_data,
+};
+
+static struct ti_clk gpt1_fck = {
+ .name = "gpt1_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt1_fck_data,
+};
+
+static struct ti_clk_gate dpll4_m2x2_ck_omap36xx_data = {
+ .parent = "dpll4_m2x2_mul_ck",
+ .bit_shift = 0x1b,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_HSDIV | CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m2x2_ck_omap36xx = {
+ .name = "dpll4_m2x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m2x2_ck_omap36xx_data,
+ .patch = &dpll4_m2x2_ck,
+};
+
+static struct ti_clk_divider gfx_l3_fck_data = {
+ .parent = "l3_ick",
+ .max_div = 7,
+ .reg = 0xb40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk gfx_l3_fck = {
+ .name = "gfx_l3_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &gfx_l3_fck_data,
+};
+
+static struct ti_clk_gate gfx_cg1_ck_data = {
+ .parent = "gfx_l3_fck",
+ .bit_shift = 1,
+ .reg = 0xb00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk gfx_cg1_ck = {
+ .name = "gfx_cg1_ck",
+ .clkdm_name = "gfx_3430es1_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gfx_cg1_ck_data,
+};
+
+static struct ti_clk_gate mailboxes_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 7,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mailboxes_ick = {
+ .name = "mailboxes_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mailboxes_ick_data,
+};
+
+static struct ti_clk_gate sha11_ick_data = {
+ .parent = "security_l4_ick2",
+ .bit_shift = 1,
+ .reg = 0xa14,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk sha11_ick = {
+ .name = "sha11_ick",
+ .type = TI_CLK_GATE,
+ .data = &sha11_ick_data,
+};
+
+static struct ti_clk_gate hsotgusb_ick_am35xx_data = {
+ .parent = "ipss_ick",
+ .bit_shift = 0,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+ .flags = CLKF_AM35XX,
+};
+
+static struct ti_clk hsotgusb_ick_am35xx = {
+ .name = "hsotgusb_ick_am35xx",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hsotgusb_ick_am35xx_data,
+};
+
+static struct ti_clk_gate mmchs3_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 30,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mmchs3_fck = {
+ .name = "mmchs3_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mmchs3_fck_data,
+};
+
+static struct ti_clk_divider pclk_fck_data = {
+ .parent = "emu_src_ck",
+ .bit_shift = 8,
+ .max_div = 7,
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk pclk_fck = {
+ .name = "pclk_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &pclk_fck_data,
+};
+
+static const char *dpll4_ck_omap36xx_parents[] = {
+ "sys_ck",
+ "sys_ck",
+};
+
+static struct ti_clk_dpll dpll4_ck_omap36xx_data = {
+ .num_parents = ARRAY_SIZE(dpll4_ck_omap36xx_parents),
+ .control_reg = 0xd00,
+ .idlest_reg = 0xd20,
+ .mult_div1_reg = 0xd44,
+ .autoidle_reg = 0xd30,
+ .module = TI_CLKM_CM,
+ .parents = dpll4_ck_omap36xx_parents,
+ .modes = 0x82,
+ .div1_mask = 0x7f,
+ .idlest_mask = 0x2,
+ .auto_recal_bit = 0x13,
+ .max_divider = 0x80,
+ .min_divider = 0x1,
+ .recal_en_bit = 0x6,
+ .max_multiplier = 0xfff,
+ .enable_mask = 0x70000,
+ .mult_mask = 0xfff00,
+ .recal_st_bit = 0x6,
+ .autoidle_mask = 0x38,
+ .sddiv_mask = 0xff000000,
+ .dco_mask = 0xe00000,
+ .flags = CLKF_PER | CLKF_J_TYPE,
+};
+
+static struct ti_clk dpll4_ck_omap36xx = {
+ .name = "dpll4_ck",
+ .type = TI_CLK_DPLL,
+ .data = &dpll4_ck_omap36xx_data,
+ .patch = &dpll4_ck,
+};
+
+static struct ti_clk_gate uart3_fck_data = {
+ .parent = "per_48m_fck",
+ .bit_shift = 11,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk uart3_fck = {
+ .name = "uart3_fck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart3_fck_data,
+};
+
+static struct ti_clk_fixed_factor wkup_32k_fck_data = {
+ .parent = "omap_32k_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk wkup_32k_fck = {
+ .name = "wkup_32k_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &wkup_32k_fck_data,
+};
+
+static struct ti_clk_gate sys_clkout1_data = {
+ .parent = "osc_sys_ck",
+ .bit_shift = 7,
+ .reg = 0xd70,
+ .module = TI_CLKM_PRM,
+};
+
+static struct ti_clk sys_clkout1 = {
+ .name = "sys_clkout1",
+ .type = TI_CLK_GATE,
+ .data = &sys_clkout1_data,
+};
+
+static struct ti_clk_fixed_factor gpmc_fck_data = {
+ .parent = "core_l3_ick",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk gpmc_fck = {
+ .name = "gpmc_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &gpmc_fck_data,
+};
+
+static struct ti_clk_fixed_factor dpll5_m2_d20_ck_data = {
+ .parent = "dpll5_m2_ck",
+ .div = 20,
+ .mult = 1,
+};
+
+static struct ti_clk dpll5_m2_d20_ck = {
+ .name = "dpll5_m2_d20_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll5_m2_d20_ck_data,
+};
+
+static struct ti_clk_gate dpll4_m5x2_ck_omap36xx_data = {
+ .parent = "dpll4_m5x2_mul_ck",
+ .bit_shift = 0x1e,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_HSDIV | CLKF_SET_RATE_PARENT | CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m5x2_ck_omap36xx = {
+ .name = "dpll4_m5x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m5x2_ck_omap36xx_data,
+ .patch = &dpll4_m5x2_ck,
+};
+
+static struct ti_clk_gate ssi_ssr_gate_fck_3430es2_data = {
+ .parent = "corex2_fck",
+ .bit_shift = 0,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_NO_WAIT,
+};
+
+static struct ti_clk_gate uart1_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 13,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk uart1_ick = {
+ .name = "uart1_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart1_ick_data,
+};
+
+static struct ti_clk_gate iva2_ck_data = {
+ .parent = "dpll2_m2_ck",
+ .bit_shift = 0,
+ .reg = 0x0,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk iva2_ck = {
+ .name = "iva2_ck",
+ .clkdm_name = "iva2_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &iva2_ck_data,
+};
+
+static struct ti_clk_gate pka_ick_data = {
+ .parent = "security_l3_ick",
+ .bit_shift = 4,
+ .reg = 0xa14,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk pka_ick = {
+ .name = "pka_ick",
+ .type = TI_CLK_GATE,
+ .data = &pka_ick_data,
+};
+
+static struct ti_clk_gate gpt12_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 1,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt12_ick = {
+ .name = "gpt12_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt12_ick_data,
+};
+
+static const char *mcbsp5_mux_fck_parents[] = {
+ "core_96m_fck",
+ "mcbsp_clks",
+};
+
+static struct ti_clk_mux mcbsp5_mux_fck_data = {
+ .bit_shift = 4,
+ .num_parents = ARRAY_SIZE(mcbsp5_mux_fck_parents),
+ .reg = 0x2d8,
+ .module = TI_CLKM_SCRM,
+ .parents = mcbsp5_mux_fck_parents,
+};
+
+static struct ti_clk_composite mcbsp5_fck_data = {
+ .mux = &mcbsp5_mux_fck_data,
+ .gate = &mcbsp5_gate_fck_data,
+};
+
+static struct ti_clk mcbsp5_fck = {
+ .name = "mcbsp5_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &mcbsp5_fck_data,
+};
+
+static struct ti_clk_gate usbhost_48m_fck_data = {
+ .parent = "omap_48m_fck",
+ .bit_shift = 0,
+ .reg = 0x1400,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_DSS,
+};
+
+static struct ti_clk usbhost_48m_fck = {
+ .name = "usbhost_48m_fck",
+ .clkdm_name = "usbhost_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &usbhost_48m_fck_data,
+};
+
+static struct ti_clk_gate des1_ick_data = {
+ .parent = "security_l4_ick2",
+ .bit_shift = 0,
+ .reg = 0xa14,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk des1_ick = {
+ .name = "des1_ick",
+ .type = TI_CLK_GATE,
+ .data = &des1_ick_data,
+};
+
+static struct ti_clk_gate sgx_gate_fck_data = {
+ .parent = "core_ck",
+ .bit_shift = 1,
+ .reg = 0xb00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_fixed_factor core_d4_ck_data = {
+ .parent = "core_ck",
+ .div = 4,
+ .mult = 1,
+};
+
+static struct ti_clk core_d4_ck = {
+ .name = "core_d4_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_d4_ck_data,
+};
+
+static struct ti_clk_fixed_factor omap_192m_alwon_fck_data = {
+ .parent = "dpll4_m2x2_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk omap_192m_alwon_fck = {
+ .name = "omap_192m_alwon_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_192m_alwon_fck_data,
+};
+
+static struct ti_clk_fixed_factor core_d2_ck_data = {
+ .parent = "core_ck",
+ .div = 2,
+ .mult = 1,
+};
+
+static struct ti_clk core_d2_ck = {
+ .name = "core_d2_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_d2_ck_data,
+};
+
+static struct ti_clk_fixed_factor corex2_d3_fck_data = {
+ .parent = "corex2_fck",
+ .div = 3,
+ .mult = 1,
+};
+
+static struct ti_clk corex2_d3_fck = {
+ .name = "corex2_d3_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &corex2_d3_fck_data,
+};
+
+static struct ti_clk_fixed_factor corex2_d5_fck_data = {
+ .parent = "corex2_fck",
+ .div = 5,
+ .mult = 1,
+};
+
+static struct ti_clk corex2_d5_fck = {
+ .name = "corex2_d5_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &corex2_d5_fck_data,
+};
+
+static const char *sgx_mux_fck_parents[] = {
+ "core_d3_ck",
+ "core_d4_ck",
+ "core_d6_ck",
+ "cm_96m_fck",
+ "omap_192m_alwon_fck",
+ "core_d2_ck",
+ "corex2_d3_fck",
+ "corex2_d5_fck",
+};
+
+static struct ti_clk_mux sgx_mux_fck_data = {
+ .num_parents = ARRAY_SIZE(sgx_mux_fck_parents),
+ .reg = 0xb40,
+ .module = TI_CLKM_CM,
+ .parents = sgx_mux_fck_parents,
+};
+
+static struct ti_clk_composite sgx_fck_data = {
+ .mux = &sgx_mux_fck_data,
+ .gate = &sgx_gate_fck_data,
+};
+
+static struct ti_clk sgx_fck = {
+ .name = "sgx_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &sgx_fck_data,
+};
+
+static struct ti_clk_gate mcspi1_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 18,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mcspi1_fck = {
+ .name = "mcspi1_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi1_fck_data,
+};
+
+static struct ti_clk_gate mmchs2_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 25,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mmchs2_fck = {
+ .name = "mmchs2_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mmchs2_fck_data,
+};
+
+static struct ti_clk_gate mcspi2_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 19,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mcspi2_fck = {
+ .name = "mcspi2_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi2_fck_data,
+};
+
+static struct ti_clk_gate vpfe_fck_data = {
+ .parent = "pclk_ck",
+ .bit_shift = 10,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+};
+
+static struct ti_clk vpfe_fck = {
+ .name = "vpfe_fck",
+ .type = TI_CLK_GATE,
+ .data = &vpfe_fck_data,
+};
+
+static struct ti_clk_gate gpt4_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 5,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_gate mcbsp1_gate_fck_data = {
+ .parent = "mcbsp_clks",
+ .bit_shift = 9,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_gate gpt5_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 6,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static const char *gpt5_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt5_mux_fck_data = {
+ .bit_shift = 3,
+ .num_parents = ARRAY_SIZE(gpt5_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt5_mux_fck_parents,
+};
+
+static struct ti_clk_composite gpt5_fck_data = {
+ .mux = &gpt5_mux_fck_data,
+ .gate = &gpt5_gate_fck_data,
+};
+
+static struct ti_clk gpt5_fck = {
+ .name = "gpt5_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt5_fck_data,
+};
+
+static struct ti_clk_gate ts_fck_data = {
+ .parent = "omap_32k_fck",
+ .bit_shift = 1,
+ .reg = 0xa08,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk ts_fck = {
+ .name = "ts_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &ts_fck_data,
+};
+
+static struct ti_clk_fixed_factor wdt1_fck_data = {
+ .parent = "secure_32k_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk wdt1_fck = {
+ .name = "wdt1_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &wdt1_fck_data,
+};
+
+static struct ti_clk_gate dpll4_m6x2_ck_omap36xx_data = {
+ .parent = "dpll4_m6x2_mul_ck",
+ .bit_shift = 0x1f,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_HSDIV | CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m6x2_ck_omap36xx = {
+ .name = "dpll4_m6x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m6x2_ck_omap36xx_data,
+ .patch = &dpll4_m6x2_ck,
+};
+
+static const char *gpt4_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt4_mux_fck_data = {
+ .bit_shift = 2,
+ .num_parents = ARRAY_SIZE(gpt4_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt4_mux_fck_parents,
+};
+
+static struct ti_clk_gate usbhost_ick_data = {
+ .parent = "l4_ick",
+ .bit_shift = 0,
+ .reg = 0x1410,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_DSS | CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk usbhost_ick = {
+ .name = "usbhost_ick",
+ .clkdm_name = "usbhost_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &usbhost_ick_data,
+};
+
+static struct ti_clk_gate mcbsp2_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 0,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcbsp2_ick = {
+ .name = "mcbsp2_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcbsp2_ick_data,
+};
+
+static struct ti_clk_gate omapctrl_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 6,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk omapctrl_ick = {
+ .name = "omapctrl_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &omapctrl_ick_data,
+};
+
+static struct ti_clk_fixed_factor omap_96m_d4_fck_data = {
+ .parent = "omap_96m_fck",
+ .div = 4,
+ .mult = 1,
+};
+
+static struct ti_clk omap_96m_d4_fck = {
+ .name = "omap_96m_d4_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_96m_d4_fck_data,
+};
+
+static struct ti_clk_gate gpt6_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 7,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt6_ick = {
+ .name = "gpt6_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt6_ick_data,
+};
+
+static struct ti_clk_gate dpll3_m3x2_ck_omap36xx_data = {
+ .parent = "dpll3_m3x2_mul_ck",
+ .bit_shift = 0xc,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_HSDIV | CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll3_m3x2_ck_omap36xx = {
+ .name = "dpll3_m3x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll3_m3x2_ck_omap36xx_data,
+ .patch = &dpll3_m3x2_ck,
+};
+
+static struct ti_clk_gate i2c3_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 17,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk i2c3_ick = {
+ .name = "i2c3_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &i2c3_ick_data,
+};
+
+static struct ti_clk_gate gpio6_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 17,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpio6_ick = {
+ .name = "gpio6_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio6_ick_data,
+};
+
+static struct ti_clk_gate mspro_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 23,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mspro_ick = {
+ .name = "mspro_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mspro_ick_data,
+};
+
+static struct ti_clk_composite mcbsp1_fck_data = {
+ .mux = &mcbsp1_mux_fck_data,
+ .gate = &mcbsp1_gate_fck_data,
+};
+
+static struct ti_clk mcbsp1_fck = {
+ .name = "mcbsp1_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &mcbsp1_fck_data,
+};
+
+static struct ti_clk_gate gpt3_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 4,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_fixed rmii_ck_data = {
+ .frequency = 50000000,
+};
+
+static struct ti_clk rmii_ck = {
+ .name = "rmii_ck",
+ .type = TI_CLK_FIXED,
+ .data = &rmii_ck_data,
+};
+
+static struct ti_clk_gate gpt6_gate_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 7,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_composite gpt6_fck_data = {
+ .mux = &gpt6_mux_fck_data,
+ .gate = &gpt6_gate_fck_data,
+};
+
+static struct ti_clk gpt6_fck = {
+ .name = "gpt6_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt6_fck_data,
+};
+
+static struct ti_clk_fixed_factor dpll5_m2_d4_ck_data = {
+ .parent = "dpll5_m2_ck",
+ .div = 4,
+ .mult = 1,
+};
+
+static struct ti_clk dpll5_m2_d4_ck = {
+ .name = "dpll5_m2_d4_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll5_m2_d4_ck_data,
+};
+
+static struct ti_clk_fixed_factor sys_d2_ck_data = {
+ .parent = "sys_ck",
+ .div = 2,
+ .mult = 1,
+};
+
+static struct ti_clk sys_d2_ck = {
+ .name = "sys_d2_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &sys_d2_ck_data,
+};
+
+static struct ti_clk_fixed_factor omap_96m_d2_fck_data = {
+ .parent = "omap_96m_fck",
+ .div = 2,
+ .mult = 1,
+};
+
+static struct ti_clk omap_96m_d2_fck = {
+ .name = "omap_96m_d2_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_96m_d2_fck_data,
+};
+
+static struct ti_clk_fixed_factor dpll5_m2_d8_ck_data = {
+ .parent = "dpll5_m2_ck",
+ .div = 8,
+ .mult = 1,
+};
+
+static struct ti_clk dpll5_m2_d8_ck = {
+ .name = "dpll5_m2_d8_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll5_m2_d8_ck_data,
+};
+
+static struct ti_clk_fixed_factor dpll5_m2_d16_ck_data = {
+ .parent = "dpll5_m2_ck",
+ .div = 16,
+ .mult = 1,
+};
+
+static struct ti_clk dpll5_m2_d16_ck = {
+ .name = "dpll5_m2_d16_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll5_m2_d16_ck_data,
+};
+
+static const char *usim_mux_fck_parents[] = {
+ "sys_ck",
+ "sys_d2_ck",
+ "omap_96m_d2_fck",
+ "omap_96m_d4_fck",
+ "omap_96m_d8_fck",
+ "omap_96m_d10_fck",
+ "dpll5_m2_d4_ck",
+ "dpll5_m2_d8_ck",
+ "dpll5_m2_d16_ck",
+ "dpll5_m2_d20_ck",
+};
+
+static struct ti_clk_mux usim_mux_fck_data = {
+ .bit_shift = 3,
+ .num_parents = ARRAY_SIZE(usim_mux_fck_parents),
+ .reg = 0xc40,
+ .module = TI_CLKM_CM,
+ .parents = usim_mux_fck_parents,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk_composite usim_fck_data = {
+ .mux = &usim_mux_fck_data,
+ .gate = &usim_gate_fck_data,
+};
+
+static struct ti_clk usim_fck = {
+ .name = "usim_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &usim_fck_data,
+};
+
+static int ssi_ssr_div_fck_3430es2_divs[] = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 0,
+ 6,
+ 0,
+ 8,
+};
+
+static struct ti_clk_divider ssi_ssr_div_fck_3430es2_data = {
+ .num_dividers = ARRAY_SIZE(ssi_ssr_div_fck_3430es2_divs),
+ .parent = "corex2_fck",
+ .bit_shift = 8,
+ .dividers = ssi_ssr_div_fck_3430es2_divs,
+ .reg = 0xa40,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_composite ssi_ssr_fck_3430es2_data = {
+ .gate = &ssi_ssr_gate_fck_3430es2_data,
+ .divider = &ssi_ssr_div_fck_3430es2_data,
+};
+
+static struct ti_clk ssi_ssr_fck_3430es2 = {
+ .name = "ssi_ssr_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &ssi_ssr_fck_3430es2_data,
+};
+
+static struct ti_clk_gate dss1_alwon_fck_3430es1_data = {
+ .parent = "dpll4_m4x2_ck",
+ .bit_shift = 0,
+ .reg = 0xe00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SET_RATE_PARENT,
+};
+
+static struct ti_clk dss1_alwon_fck_3430es1 = {
+ .name = "dss1_alwon_fck",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss1_alwon_fck_3430es1_data,
+};
+
+static struct ti_clk_gate gpt3_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 4,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt3_ick = {
+ .name = "gpt3_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt3_ick_data,
+};
+
+static struct ti_clk_fixed_factor omap_12m_fck_data = {
+ .parent = "omap_48m_fck",
+ .div = 4,
+ .mult = 1,
+};
+
+static struct ti_clk omap_12m_fck = {
+ .name = "omap_12m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &omap_12m_fck_data,
+};
+
+static struct ti_clk_fixed_factor core_12m_fck_data = {
+ .parent = "omap_12m_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk core_12m_fck = {
+ .name = "core_12m_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &core_12m_fck_data,
+};
+
+static struct ti_clk_gate hdq_fck_data = {
+ .parent = "core_12m_fck",
+ .bit_shift = 22,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk hdq_fck = {
+ .name = "hdq_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hdq_fck_data,
+};
+
+static struct ti_clk_gate usbtll_fck_data = {
+ .parent = "dpll5_m2_ck",
+ .bit_shift = 2,
+ .reg = 0xa08,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk usbtll_fck = {
+ .name = "usbtll_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &usbtll_fck_data,
+};
+
+static struct ti_clk_gate hsotgusb_fck_am35xx_data = {
+ .parent = "sys_ck",
+ .bit_shift = 8,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+};
+
+static struct ti_clk hsotgusb_fck_am35xx = {
+ .name = "hsotgusb_fck_am35xx",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hsotgusb_fck_am35xx_data,
+};
+
+static struct ti_clk_gate hsotgusb_ick_3430es2_data = {
+ .parent = "core_l3_ick",
+ .bit_shift = 4,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_HSOTGUSB | CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk hsotgusb_ick_3430es2 = {
+ .name = "hsotgusb_ick_3430es2",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hsotgusb_ick_3430es2_data,
+};
+
+static struct ti_clk_gate gfx_l3_ck_data = {
+ .parent = "l3_ick",
+ .bit_shift = 0,
+ .reg = 0xb10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk gfx_l3_ck = {
+ .name = "gfx_l3_ck",
+ .clkdm_name = "gfx_3430es1_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gfx_l3_ck_data,
+};
+
+static struct ti_clk_fixed_factor gfx_l3_ick_data = {
+ .parent = "gfx_l3_ck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk gfx_l3_ick = {
+ .name = "gfx_l3_ick",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &gfx_l3_ick_data,
+};
+
+static struct ti_clk_gate mcbsp1_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 9,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcbsp1_ick = {
+ .name = "mcbsp1_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcbsp1_ick_data,
+};
+
+static struct ti_clk_fixed_factor gpt12_fck_data = {
+ .parent = "secure_32k_fck",
+ .div = 1,
+ .mult = 1,
+};
+
+static struct ti_clk gpt12_fck = {
+ .name = "gpt12_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &gpt12_fck_data,
+};
+
+static struct ti_clk_gate gfx_cg2_ck_data = {
+ .parent = "gfx_l3_fck",
+ .bit_shift = 2,
+ .reg = 0xb00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk gfx_cg2_ck = {
+ .name = "gfx_cg2_ck",
+ .clkdm_name = "gfx_3430es1_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gfx_cg2_ck_data,
+};
+
+static struct ti_clk_gate i2c2_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 16,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk i2c2_ick = {
+ .name = "i2c2_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &i2c2_ick_data,
+};
+
+static struct ti_clk_gate gpio4_dbck_data = {
+ .parent = "per_32k_alwon_fck",
+ .bit_shift = 15,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk gpio4_dbck = {
+ .name = "gpio4_dbck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio4_dbck_data,
+};
+
+static struct ti_clk_gate i2c3_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 17,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk i2c3_fck = {
+ .name = "i2c3_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &i2c3_fck_data,
+};
+
+static struct ti_clk_composite gpt3_fck_data = {
+ .mux = &gpt3_mux_fck_data,
+ .gate = &gpt3_gate_fck_data,
+};
+
+static struct ti_clk gpt3_fck = {
+ .name = "gpt3_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt3_fck_data,
+};
+
+static struct ti_clk_gate i2c1_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 15,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk i2c1_ick = {
+ .name = "i2c1_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &i2c1_ick_data,
+};
+
+static struct ti_clk_gate omap_32ksync_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 2,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk omap_32ksync_ick = {
+ .name = "omap_32ksync_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &omap_32ksync_ick_data,
+};
+
+static struct ti_clk_gate aes2_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 28,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk aes2_ick = {
+ .name = "aes2_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &aes2_ick_data,
+};
+
+static const char *gpt8_mux_fck_parents[] = {
+ "omap_32k_fck",
+ "sys_ck",
+};
+
+static struct ti_clk_mux gpt8_mux_fck_data = {
+ .bit_shift = 6,
+ .num_parents = ARRAY_SIZE(gpt8_mux_fck_parents),
+ .reg = 0x1040,
+ .module = TI_CLKM_CM,
+ .parents = gpt8_mux_fck_parents,
+};
+
+static struct ti_clk_composite gpt8_fck_data = {
+ .mux = &gpt8_mux_fck_data,
+ .gate = &gpt8_gate_fck_data,
+};
+
+static struct ti_clk gpt8_fck = {
+ .name = "gpt8_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt8_fck_data,
+};
+
+static struct ti_clk_gate mcbsp4_gate_fck_data = {
+ .parent = "mcbsp_clks",
+ .bit_shift = 2,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk_composite mcbsp4_fck_data = {
+ .mux = &mcbsp4_mux_fck_data,
+ .gate = &mcbsp4_gate_fck_data,
+};
+
+static struct ti_clk mcbsp4_fck = {
+ .name = "mcbsp4_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &mcbsp4_fck_data,
+};
+
+static struct ti_clk_gate gpio2_dbck_data = {
+ .parent = "per_32k_alwon_fck",
+ .bit_shift = 13,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk gpio2_dbck = {
+ .name = "gpio2_dbck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio2_dbck_data,
+};
+
+static struct ti_clk_gate usbtll_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 2,
+ .reg = 0xa18,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk usbtll_ick = {
+ .name = "usbtll_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &usbtll_ick_data,
+};
+
+static struct ti_clk_gate mcspi4_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 21,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcspi4_ick = {
+ .name = "mcspi4_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi4_ick_data,
+};
+
+static struct ti_clk_gate dss_96m_fck_data = {
+ .parent = "omap_96m_fck",
+ .bit_shift = 2,
+ .reg = 0xe00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk dss_96m_fck = {
+ .name = "dss_96m_fck",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss_96m_fck_data,
+};
+
+static struct ti_clk_divider rm_ick_data = {
+ .parent = "l4_ick",
+ .bit_shift = 1,
+ .max_div = 3,
+ .reg = 0xc40,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk rm_ick = {
+ .name = "rm_ick",
+ .type = TI_CLK_DIVIDER,
+ .data = &rm_ick_data,
+};
+
+static struct ti_clk_gate hdq_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 22,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk hdq_ick = {
+ .name = "hdq_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &hdq_ick_data,
+};
+
+static struct ti_clk_fixed_factor dpll3_x2_ck_data = {
+ .parent = "dpll3_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll3_x2_ck = {
+ .name = "dpll3_x2_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll3_x2_ck_data,
+};
+
+static struct ti_clk_gate mad2d_ick_data = {
+ .parent = "l3_ick",
+ .bit_shift = 3,
+ .reg = 0xa18,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mad2d_ick = {
+ .name = "mad2d_ick",
+ .clkdm_name = "d2d_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mad2d_ick_data,
+};
+
+static struct ti_clk_gate fshostusb_fck_data = {
+ .parent = "core_48m_fck",
+ .bit_shift = 5,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk fshostusb_fck = {
+ .name = "fshostusb_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &fshostusb_fck_data,
+};
+
+static struct ti_clk_gate sr1_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 6,
+ .reg = 0xc00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk sr1_fck = {
+ .name = "sr1_fck",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &sr1_fck_data,
+};
+
+static struct ti_clk_gate des2_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 26,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk des2_ick = {
+ .name = "des2_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &des2_ick_data,
+};
+
+static struct ti_clk_gate sdrc_ick_data = {
+ .parent = "core_l3_ick",
+ .bit_shift = 1,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk sdrc_ick = {
+ .name = "sdrc_ick",
+ .clkdm_name = "core_l3_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &sdrc_ick_data,
+};
+
+static struct ti_clk_composite gpt4_fck_data = {
+ .mux = &gpt4_mux_fck_data,
+ .gate = &gpt4_gate_fck_data,
+};
+
+static struct ti_clk gpt4_fck = {
+ .name = "gpt4_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt4_fck_data,
+};
+
+static struct ti_clk_gate dpll4_m3x2_ck_omap36xx_data = {
+ .parent = "dpll4_m3x2_mul_ck",
+ .bit_shift = 0x1c,
+ .reg = 0xd00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_HSDIV | CLKF_SET_BIT_TO_DISABLE,
+};
+
+static struct ti_clk dpll4_m3x2_ck_omap36xx = {
+ .name = "dpll4_m3x2_ck",
+ .type = TI_CLK_GATE,
+ .data = &dpll4_m3x2_ck_omap36xx_data,
+ .patch = &dpll4_m3x2_ck,
+};
+
+static struct ti_clk_gate cpefuse_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 0,
+ .reg = 0xa08,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk cpefuse_fck = {
+ .name = "cpefuse_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &cpefuse_fck_data,
+};
+
+static struct ti_clk_gate mcspi3_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 20,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcspi3_ick = {
+ .name = "mcspi3_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi3_ick_data,
+};
+
+static struct ti_clk_fixed_factor ssi_sst_fck_3430es2_data = {
+ .parent = "ssi_ssr_fck",
+ .div = 2,
+ .mult = 1,
+};
+
+static struct ti_clk ssi_sst_fck_3430es2 = {
+ .name = "ssi_sst_fck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &ssi_sst_fck_3430es2_data,
+};
+
+static struct ti_clk_gate gpio1_dbck_data = {
+ .parent = "wkup_32k_fck",
+ .bit_shift = 3,
+ .reg = 0xc00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk gpio1_dbck = {
+ .name = "gpio1_dbck",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio1_dbck_data,
+};
+
+static struct ti_clk_gate gpt4_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 5,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt4_ick = {
+ .name = "gpt4_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt4_ick_data,
+};
+
+static struct ti_clk_gate gpt2_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 3,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt2_ick = {
+ .name = "gpt2_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt2_ick_data,
+};
+
+static struct ti_clk_gate mmchs1_fck_data = {
+ .parent = "core_96m_fck",
+ .bit_shift = 24,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk mmchs1_fck = {
+ .name = "mmchs1_fck",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mmchs1_fck_data,
+};
+
+static struct ti_clk_fixed dummy_apb_pclk_data = {
+ .frequency = 0x0,
+};
+
+static struct ti_clk dummy_apb_pclk = {
+ .name = "dummy_apb_pclk",
+ .type = TI_CLK_FIXED,
+ .data = &dummy_apb_pclk_data,
+};
+
+static struct ti_clk_gate gpio6_dbck_data = {
+ .parent = "per_32k_alwon_fck",
+ .bit_shift = 17,
+ .reg = 0x1000,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk gpio6_dbck = {
+ .name = "gpio6_dbck",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio6_dbck_data,
+};
+
+static struct ti_clk_gate uart2_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 14,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk uart2_ick = {
+ .name = "uart2_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &uart2_ick_data,
+};
+
+static struct ti_clk_fixed_factor dpll4_x2_ck_data = {
+ .parent = "dpll4_ck",
+ .div = 1,
+ .mult = 2,
+};
+
+static struct ti_clk dpll4_x2_ck = {
+ .name = "dpll4_x2_ck",
+ .type = TI_CLK_FIXED_FACTOR,
+ .data = &dpll4_x2_ck_data,
+};
+
+static struct ti_clk_gate gpt7_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 8,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpt7_ick = {
+ .name = "gpt7_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpt7_ick_data,
+};
+
+static struct ti_clk_gate dss_tv_fck_data = {
+ .parent = "omap_54m_fck",
+ .bit_shift = 2,
+ .reg = 0xe00,
+ .module = TI_CLKM_CM,
+};
+
+static struct ti_clk dss_tv_fck = {
+ .name = "dss_tv_fck",
+ .clkdm_name = "dss_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &dss_tv_fck_data,
+};
+
+static struct ti_clk_gate mcbsp5_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 10,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcbsp5_ick = {
+ .name = "mcbsp5_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcbsp5_ick_data,
+};
+
+static struct ti_clk_gate mcspi1_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 18,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk mcspi1_ick = {
+ .name = "mcspi1_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &mcspi1_ick_data,
+};
+
+static struct ti_clk_gate d2d_26m_fck_data = {
+ .parent = "sys_ck",
+ .bit_shift = 3,
+ .reg = 0xa00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk d2d_26m_fck = {
+ .name = "d2d_26m_fck",
+ .clkdm_name = "d2d_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &d2d_26m_fck_data,
+};
+
+static struct ti_clk_gate wdt3_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 12,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk wdt3_ick = {
+ .name = "wdt3_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &wdt3_ick_data,
+};
+
+static struct ti_clk_divider pclkx2_fck_data = {
+ .parent = "emu_src_ck",
+ .bit_shift = 6,
+ .max_div = 3,
+ .reg = 0x1140,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_STARTS_AT_ONE,
+};
+
+static struct ti_clk pclkx2_fck = {
+ .name = "pclkx2_fck",
+ .type = TI_CLK_DIVIDER,
+ .data = &pclkx2_fck_data,
+};
+
+static struct ti_clk_gate sha12_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 27,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk sha12_ick = {
+ .name = "sha12_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &sha12_ick_data,
+};
+
+static struct ti_clk_gate emac_fck_data = {
+ .parent = "rmii_ck",
+ .bit_shift = 9,
+ .reg = 0x59c,
+ .module = TI_CLKM_SCRM,
+};
+
+static struct ti_clk emac_fck = {
+ .name = "emac_fck",
+ .type = TI_CLK_GATE,
+ .data = &emac_fck_data,
+};
+
+static struct ti_clk_composite gpt10_fck_data = {
+ .mux = &gpt10_mux_fck_data,
+ .gate = &gpt10_gate_fck_data,
+};
+
+static struct ti_clk gpt10_fck = {
+ .name = "gpt10_fck",
+ .type = TI_CLK_COMPOSITE,
+ .data = &gpt10_fck_data,
+};
+
+static struct ti_clk_gate wdt2_fck_data = {
+ .parent = "wkup_32k_fck",
+ .bit_shift = 5,
+ .reg = 0xc00,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk wdt2_fck = {
+ .name = "wdt2_fck",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &wdt2_fck_data,
+};
+
+static struct ti_clk_gate cam_ick_data = {
+ .parent = "l4_ick",
+ .bit_shift = 0,
+ .reg = 0xf10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_NO_WAIT | CLKF_INTERFACE,
+};
+
+static struct ti_clk cam_ick = {
+ .name = "cam_ick",
+ .clkdm_name = "cam_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &cam_ick_data,
+};
+
+static struct ti_clk_gate ssi_ick_3430es2_data = {
+ .parent = "ssi_l4_ick",
+ .bit_shift = 0,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_SSI | CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk ssi_ick_3430es2 = {
+ .name = "ssi_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &ssi_ick_3430es2_data,
+};
+
+static struct ti_clk_gate gpio4_ick_data = {
+ .parent = "per_l4_ick",
+ .bit_shift = 15,
+ .reg = 0x1010,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk gpio4_ick = {
+ .name = "gpio4_ick",
+ .clkdm_name = "per_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &gpio4_ick_data,
+};
+
+static struct ti_clk_gate wdt1_ick_data = {
+ .parent = "wkup_l4_ick",
+ .bit_shift = 4,
+ .reg = 0xc10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk wdt1_ick = {
+ .name = "wdt1_ick",
+ .clkdm_name = "wkup_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &wdt1_ick_data,
+};
+
+static struct ti_clk_gate rng_ick_data = {
+ .parent = "security_l4_ick2",
+ .bit_shift = 2,
+ .reg = 0xa14,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk rng_ick = {
+ .name = "rng_ick",
+ .type = TI_CLK_GATE,
+ .data = &rng_ick_data,
+};
+
+static struct ti_clk_gate icr_ick_data = {
+ .parent = "core_l4_ick",
+ .bit_shift = 29,
+ .reg = 0xa10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_OMAP3 | CLKF_INTERFACE,
+};
+
+static struct ti_clk icr_ick = {
+ .name = "icr_ick",
+ .clkdm_name = "core_l4_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &icr_ick_data,
+};
+
+static struct ti_clk_gate sgx_ick_data = {
+ .parent = "l3_ick",
+ .bit_shift = 0,
+ .reg = 0xb10,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_WAIT,
+};
+
+static struct ti_clk sgx_ick = {
+ .name = "sgx_ick",
+ .clkdm_name = "sgx_clkdm",
+ .type = TI_CLK_GATE,
+ .data = &sgx_ick_data,
+};
+
+static struct ti_clk_divider sys_clkout2_data = {
+ .parent = "clkout2_src_ck",
+ .bit_shift = 3,
+ .max_div = 64,
+ .reg = 0xd70,
+ .module = TI_CLKM_CM,
+ .flags = CLKF_INDEX_POWER_OF_TWO,
+};
+
+static struct ti_clk sys_clkout2 = {
+ .name = "sys_clkout2",
+ .type = TI_CLK_DIVIDER,
+ .data = &sys_clkout2_data,
+};
+
+static struct ti_clk_alias omap34xx_omap36xx_clks[] = {
+ CLK(NULL, "security_l4_ick2", &security_l4_ick2),
+ CLK(NULL, "aes1_ick", &aes1_ick),
+ CLK("omap_rng", "ick", &rng_ick),
+ CLK("omap3-rom-rng", "ick", &rng_ick),
+ CLK(NULL, "sha11_ick", &sha11_ick),
+ CLK(NULL, "des1_ick", &des1_ick),
+ CLK(NULL, "cam_mclk", &cam_mclk),
+ CLK(NULL, "cam_ick", &cam_ick),
+ CLK(NULL, "csi2_96m_fck", &csi2_96m_fck),
+ CLK(NULL, "security_l3_ick", &security_l3_ick),
+ CLK(NULL, "pka_ick", &pka_ick),
+ CLK(NULL, "icr_ick", &icr_ick),
+ CLK(NULL, "des2_ick", &des2_ick),
+ CLK(NULL, "mspro_ick", &mspro_ick),
+ CLK(NULL, "mailboxes_ick", &mailboxes_ick),
+ CLK(NULL, "ssi_l4_ick", &ssi_l4_ick),
+ CLK(NULL, "sr1_fck", &sr1_fck),
+ CLK(NULL, "sr2_fck", &sr2_fck),
+ CLK(NULL, "sr_l4_ick", &sr_l4_ick),
+ CLK(NULL, "dpll2_fck", &dpll2_fck),
+ CLK(NULL, "dpll2_ck", &dpll2_ck),
+ CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck),
+ CLK(NULL, "iva2_ck", &iva2_ck),
+ CLK(NULL, "modem_fck", &modem_fck),
+ CLK(NULL, "sad2d_ick", &sad2d_ick),
+ CLK(NULL, "mad2d_ick", &mad2d_ick),
+ CLK(NULL, "mspro_fck", &mspro_fck),
+ { NULL },
+};
+
+static struct ti_clk_alias omap36xx_omap3430es2plus_clks[] = {
+ CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2),
+ CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2),
+ CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es2),
+ CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es2),
+ CLK(NULL, "ssi_ick", &ssi_ick_3430es2),
+ CLK(NULL, "sys_d2_ck", &sys_d2_ck),
+ CLK(NULL, "omap_96m_d2_fck", &omap_96m_d2_fck),
+ CLK(NULL, "omap_96m_d4_fck", &omap_96m_d4_fck),
+ CLK(NULL, "omap_96m_d8_fck", &omap_96m_d8_fck),
+ CLK(NULL, "omap_96m_d10_fck", &omap_96m_d10_fck),
+ CLK(NULL, "dpll5_m2_d4_ck", &dpll5_m2_d4_ck),
+ CLK(NULL, "dpll5_m2_d8_ck", &dpll5_m2_d8_ck),
+ CLK(NULL, "dpll5_m2_d16_ck", &dpll5_m2_d16_ck),
+ CLK(NULL, "dpll5_m2_d20_ck", &dpll5_m2_d20_ck),
+ CLK(NULL, "usim_fck", &usim_fck),
+ CLK(NULL, "usim_ick", &usim_ick),
+ { NULL },
+};
+
+static struct ti_clk_alias omap3xxx_clks[] = {
+ CLK(NULL, "apb_pclk", &dummy_apb_pclk),
+ CLK(NULL, "omap_32k_fck", &omap_32k_fck),
+ CLK(NULL, "virt_12m_ck", &virt_12m_ck),
+ CLK(NULL, "virt_13m_ck", &virt_13m_ck),
+ CLK(NULL, "virt_19200000_ck", &virt_19200000_ck),
+ CLK(NULL, "virt_26000000_ck", &virt_26000000_ck),
+ CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck),
+ CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck),
+ CLK(NULL, "osc_sys_ck", &osc_sys_ck),
+ CLK("twl", "fck", &osc_sys_ck),
+ CLK(NULL, "sys_ck", &sys_ck),
+ CLK(NULL, "timer_sys_ck", &sys_ck),
+ CLK(NULL, "dpll4_ck", &dpll4_ck),
+ CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck),
+ CLK(NULL, "dpll4_m2x2_mul_ck", &dpll4_m2x2_mul_ck),
+ CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck),
+ CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck),
+ CLK(NULL, "dpll3_ck", &dpll3_ck),
+ CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck),
+ CLK(NULL, "dpll3_m3x2_mul_ck", &dpll3_m3x2_mul_ck),
+ CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck),
+ CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck),
+ CLK(NULL, "sys_altclk", &sys_altclk),
+ CLK(NULL, "mcbsp_clks", &mcbsp_clks),
+ CLK(NULL, "sys_clkout1", &sys_clkout1),
+ CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck),
+ CLK(NULL, "core_ck", &core_ck),
+ CLK(NULL, "dpll1_fck", &dpll1_fck),
+ CLK(NULL, "dpll1_ck", &dpll1_ck),
+ CLK(NULL, "cpufreq_ck", &dpll1_ck),
+ CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck),
+ CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck),
+ CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck),
+ CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck),
+ CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck),
+ CLK(NULL, "cm_96m_fck", &cm_96m_fck),
+ CLK(NULL, "omap_96m_fck", &omap_96m_fck),
+ CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck),
+ CLK(NULL, "dpll4_m3x2_mul_ck", &dpll4_m3x2_mul_ck),
+ CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck),
+ CLK(NULL, "omap_54m_fck", &omap_54m_fck),
+ CLK(NULL, "cm_96m_d2_fck", &cm_96m_d2_fck),
+ CLK(NULL, "omap_48m_fck", &omap_48m_fck),
+ CLK(NULL, "omap_12m_fck", &omap_12m_fck),
+ CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck),
+ CLK(NULL, "dpll4_m4x2_mul_ck", &dpll4_m4x2_mul_ck),
+ CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck),
+ CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck),
+ CLK(NULL, "dpll4_m5x2_mul_ck", &dpll4_m5x2_mul_ck),
+ CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck),
+ CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck),
+ CLK(NULL, "dpll4_m6x2_mul_ck", &dpll4_m6x2_mul_ck),
+ CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck),
+ CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck),
+ CLK(NULL, "clkout2_src_ck", &clkout2_src_ck),
+ CLK(NULL, "sys_clkout2", &sys_clkout2),
+ CLK(NULL, "corex2_fck", &corex2_fck),
+ CLK(NULL, "mpu_ck", &mpu_ck),
+ CLK(NULL, "arm_fck", &arm_fck),
+ CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck),
+ CLK(NULL, "l3_ick", &l3_ick),
+ CLK(NULL, "l4_ick", &l4_ick),
+ CLK(NULL, "rm_ick", &rm_ick),
+ CLK(NULL, "timer_32k_ck", &omap_32k_fck),
+ CLK(NULL, "gpt10_fck", &gpt10_fck),
+ CLK(NULL, "gpt11_fck", &gpt11_fck),
+ CLK(NULL, "core_96m_fck", &core_96m_fck),
+ CLK(NULL, "mmchs2_fck", &mmchs2_fck),
+ CLK(NULL, "mmchs1_fck", &mmchs1_fck),
+ CLK(NULL, "i2c3_fck", &i2c3_fck),
+ CLK(NULL, "i2c2_fck", &i2c2_fck),
+ CLK(NULL, "i2c1_fck", &i2c1_fck),
+ CLK(NULL, "mcbsp5_fck", &mcbsp5_fck),
+ CLK(NULL, "mcbsp1_fck", &mcbsp1_fck),
+ CLK(NULL, "core_48m_fck", &core_48m_fck),
+ CLK(NULL, "mcspi4_fck", &mcspi4_fck),
+ CLK(NULL, "mcspi3_fck", &mcspi3_fck),
+ CLK(NULL, "mcspi2_fck", &mcspi2_fck),
+ CLK(NULL, "mcspi1_fck", &mcspi1_fck),
+ CLK(NULL, "uart2_fck", &uart2_fck),
+ CLK(NULL, "uart1_fck", &uart1_fck),
+ CLK(NULL, "core_12m_fck", &core_12m_fck),
+ CLK("omap_hdq.0", "fck", &hdq_fck),
+ CLK(NULL, "hdq_fck", &hdq_fck),
+ CLK(NULL, "core_l3_ick", &core_l3_ick),
+ CLK(NULL, "sdrc_ick", &sdrc_ick),
+ CLK(NULL, "gpmc_fck", &gpmc_fck),
+ CLK(NULL, "core_l4_ick", &core_l4_ick),
+ CLK("omap_hsmmc.1", "ick", &mmchs2_ick),
+ CLK("omap_hsmmc.0", "ick", &mmchs1_ick),
+ CLK(NULL, "mmchs2_ick", &mmchs2_ick),
+ CLK(NULL, "mmchs1_ick", &mmchs1_ick),
+ CLK("omap_hdq.0", "ick", &hdq_ick),
+ CLK(NULL, "hdq_ick", &hdq_ick),
+ CLK("omap2_mcspi.4", "ick", &mcspi4_ick),
+ CLK("omap2_mcspi.3", "ick", &mcspi3_ick),
+ CLK("omap2_mcspi.2", "ick", &mcspi2_ick),
+ CLK("omap2_mcspi.1", "ick", &mcspi1_ick),
+ CLK(NULL, "mcspi4_ick", &mcspi4_ick),
+ CLK(NULL, "mcspi3_ick", &mcspi3_ick),
+ CLK(NULL, "mcspi2_ick", &mcspi2_ick),
+ CLK(NULL, "mcspi1_ick", &mcspi1_ick),
+ CLK("omap_i2c.3", "ick", &i2c3_ick),
+ CLK("omap_i2c.2", "ick", &i2c2_ick),
+ CLK("omap_i2c.1", "ick", &i2c1_ick),
+ CLK(NULL, "i2c3_ick", &i2c3_ick),
+ CLK(NULL, "i2c2_ick", &i2c2_ick),
+ CLK(NULL, "i2c1_ick", &i2c1_ick),
+ CLK(NULL, "uart2_ick", &uart2_ick),
+ CLK(NULL, "uart1_ick", &uart1_ick),
+ CLK(NULL, "gpt11_ick", &gpt11_ick),
+ CLK(NULL, "gpt10_ick", &gpt10_ick),
+ CLK("omap-mcbsp.5", "ick", &mcbsp5_ick),
+ CLK("omap-mcbsp.1", "ick", &mcbsp1_ick),
+ CLK(NULL, "mcbsp5_ick", &mcbsp5_ick),
+ CLK(NULL, "mcbsp1_ick", &mcbsp1_ick),
+ CLK(NULL, "omapctrl_ick", &omapctrl_ick),
+ CLK(NULL, "dss_tv_fck", &dss_tv_fck),
+ CLK(NULL, "dss_96m_fck", &dss_96m_fck),
+ CLK(NULL, "dss2_alwon_fck", &dss2_alwon_fck),
+ CLK(NULL, "init_60m_fclk", &dummy_ck),
+ CLK(NULL, "gpt1_fck", &gpt1_fck),
+ CLK(NULL, "aes2_ick", &aes2_ick),
+ CLK(NULL, "wkup_32k_fck", &wkup_32k_fck),
+ CLK(NULL, "gpio1_dbck", &gpio1_dbck),
+ CLK(NULL, "sha12_ick", &sha12_ick),
+ CLK(NULL, "wdt2_fck", &wdt2_fck),
+ CLK(NULL, "wkup_l4_ick", &wkup_l4_ick),
+ CLK("omap_wdt", "ick", &wdt2_ick),
+ CLK(NULL, "wdt2_ick", &wdt2_ick),
+ CLK(NULL, "wdt1_ick", &wdt1_ick),
+ CLK(NULL, "gpio1_ick", &gpio1_ick),
+ CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick),
+ CLK(NULL, "gpt12_ick", &gpt12_ick),
+ CLK(NULL, "gpt1_ick", &gpt1_ick),
+ CLK(NULL, "per_96m_fck", &per_96m_fck),
+ CLK(NULL, "per_48m_fck", &per_48m_fck),
+ CLK(NULL, "uart3_fck", &uart3_fck),
+ CLK(NULL, "gpt2_fck", &gpt2_fck),
+ CLK(NULL, "gpt3_fck", &gpt3_fck),
+ CLK(NULL, "gpt4_fck", &gpt4_fck),
+ CLK(NULL, "gpt5_fck", &gpt5_fck),
+ CLK(NULL, "gpt6_fck", &gpt6_fck),
+ CLK(NULL, "gpt7_fck", &gpt7_fck),
+ CLK(NULL, "gpt8_fck", &gpt8_fck),
+ CLK(NULL, "gpt9_fck", &gpt9_fck),
+ CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck),
+ CLK(NULL, "gpio6_dbck", &gpio6_dbck),
+ CLK(NULL, "gpio5_dbck", &gpio5_dbck),
+ CLK(NULL, "gpio4_dbck", &gpio4_dbck),
+ CLK(NULL, "gpio3_dbck", &gpio3_dbck),
+ CLK(NULL, "gpio2_dbck", &gpio2_dbck),
+ CLK(NULL, "wdt3_fck", &wdt3_fck),
+ CLK(NULL, "per_l4_ick", &per_l4_ick),
+ CLK(NULL, "gpio6_ick", &gpio6_ick),
+ CLK(NULL, "gpio5_ick", &gpio5_ick),
+ CLK(NULL, "gpio4_ick", &gpio4_ick),
+ CLK(NULL, "gpio3_ick", &gpio3_ick),
+ CLK(NULL, "gpio2_ick", &gpio2_ick),
+ CLK(NULL, "wdt3_ick", &wdt3_ick),
+ CLK(NULL, "uart3_ick", &uart3_ick),
+ CLK(NULL, "uart4_ick", &uart4_ick),
+ CLK(NULL, "gpt9_ick", &gpt9_ick),
+ CLK(NULL, "gpt8_ick", &gpt8_ick),
+ CLK(NULL, "gpt7_ick", &gpt7_ick),
+ CLK(NULL, "gpt6_ick", &gpt6_ick),
+ CLK(NULL, "gpt5_ick", &gpt5_ick),
+ CLK(NULL, "gpt4_ick", &gpt4_ick),
+ CLK(NULL, "gpt3_ick", &gpt3_ick),
+ CLK(NULL, "gpt2_ick", &gpt2_ick),
+ CLK("omap-mcbsp.2", "ick", &mcbsp2_ick),
+ CLK("omap-mcbsp.3", "ick", &mcbsp3_ick),
+ CLK("omap-mcbsp.4", "ick", &mcbsp4_ick),
+ CLK(NULL, "mcbsp4_ick", &mcbsp2_ick),
+ CLK(NULL, "mcbsp3_ick", &mcbsp3_ick),
+ CLK(NULL, "mcbsp2_ick", &mcbsp4_ick),
+ CLK(NULL, "mcbsp2_fck", &mcbsp2_fck),
+ CLK(NULL, "mcbsp3_fck", &mcbsp3_fck),
+ CLK(NULL, "mcbsp4_fck", &mcbsp4_fck),
+ CLK(NULL, "emu_src_mux_ck", &emu_src_mux_ck),
+ CLK("etb", "emu_src_ck", &emu_src_ck),
+ CLK(NULL, "emu_src_mux_ck", &emu_src_mux_ck),
+ CLK(NULL, "emu_src_ck", &emu_src_ck),
+ CLK(NULL, "pclk_fck", &pclk_fck),
+ CLK(NULL, "pclkx2_fck", &pclkx2_fck),
+ CLK(NULL, "atclk_fck", &atclk_fck),
+ CLK(NULL, "traceclk_src_fck", &traceclk_src_fck),
+ CLK(NULL, "traceclk_fck", &traceclk_fck),
+ CLK(NULL, "secure_32k_fck", &secure_32k_fck),
+ CLK(NULL, "gpt12_fck", &gpt12_fck),
+ CLK(NULL, "wdt1_fck", &wdt1_fck),
+ { NULL },
+};
+
+static struct ti_clk_alias omap36xx_am35xx_omap3430es2plus_clks[] = {
+ CLK(NULL, "dpll5_ck", &dpll5_ck),
+ CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck),
+ CLK(NULL, "core_d3_ck", &core_d3_ck),
+ CLK(NULL, "core_d4_ck", &core_d4_ck),
+ CLK(NULL, "core_d6_ck", &core_d6_ck),
+ CLK(NULL, "omap_192m_alwon_fck", &omap_192m_alwon_fck),
+ CLK(NULL, "core_d2_ck", &core_d2_ck),
+ CLK(NULL, "corex2_d3_fck", &corex2_d3_fck),
+ CLK(NULL, "corex2_d5_fck", &corex2_d5_fck),
+ CLK(NULL, "sgx_fck", &sgx_fck),
+ CLK(NULL, "sgx_ick", &sgx_ick),
+ CLK(NULL, "cpefuse_fck", &cpefuse_fck),
+ CLK(NULL, "ts_fck", &ts_fck),
+ CLK(NULL, "usbtll_fck", &usbtll_fck),
+ CLK(NULL, "usbtll_ick", &usbtll_ick),
+ CLK("omap_hsmmc.2", "ick", &mmchs3_ick),
+ CLK(NULL, "mmchs3_ick", &mmchs3_ick),
+ CLK(NULL, "mmchs3_fck", &mmchs3_fck),
+ CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es2),
+ CLK("omapdss_dss", "ick", &dss_ick_3430es2),
+ CLK(NULL, "dss_ick", &dss_ick_3430es2),
+ CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck),
+ CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck),
+ CLK(NULL, "usbhost_ick", &usbhost_ick),
+ { NULL },
+};
+
+static struct ti_clk_alias omap3430es1_clks[] = {
+ CLK(NULL, "gfx_l3_ck", &gfx_l3_ck),
+ CLK(NULL, "gfx_l3_fck", &gfx_l3_fck),
+ CLK(NULL, "gfx_l3_ick", &gfx_l3_ick),
+ CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck),
+ CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck),
+ CLK(NULL, "d2d_26m_fck", &d2d_26m_fck),
+ CLK(NULL, "fshostusb_fck", &fshostusb_fck),
+ CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1),
+ CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1),
+ CLK("musb-omap2430", "ick", &hsotgusb_ick_3430es1),
+ CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_3430es1),
+ CLK(NULL, "fac_ick", &fac_ick),
+ CLK(NULL, "ssi_ick", &ssi_ick_3430es1),
+ CLK(NULL, "usb_l4_ick", &usb_l4_ick),
+ CLK(NULL, "dss1_alwon_fck", &dss1_alwon_fck_3430es1),
+ CLK("omapdss_dss", "ick", &dss_ick_3430es1),
+ CLK(NULL, "dss_ick", &dss_ick_3430es1),
+ { NULL },
+};
+
+static struct ti_clk_alias omap36xx_clks[] = {
+ CLK(NULL, "uart4_fck", &uart4_fck),
+ { NULL },
+};
+
+static struct ti_clk_alias am35xx_clks[] = {
+ CLK(NULL, "ipss_ick", &ipss_ick),
+ CLK(NULL, "rmii_ck", &rmii_ck),
+ CLK(NULL, "pclk_ck", &pclk_ck),
+ CLK(NULL, "emac_ick", &emac_ick),
+ CLK(NULL, "emac_fck", &emac_fck),
+ CLK("davinci_emac.0", NULL, &emac_ick),
+ CLK("davinci_mdio.0", NULL, &emac_fck),
+ CLK("vpfe-capture", "master", &vpfe_ick),
+ CLK("vpfe-capture", "slave", &vpfe_fck),
+ CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_am35xx),
+ CLK(NULL, "hsotgusb_fck", &hsotgusb_fck_am35xx),
+ CLK(NULL, "hecc_ck", &hecc_ck),
+ CLK(NULL, "uart4_ick", &uart4_ick_am35xx),
+ CLK(NULL, "uart4_fck", &uart4_fck_am35xx),
+ { NULL },
+};
+
+static struct ti_clk *omap36xx_clk_patches[] = {
+ &dpll4_m3x2_ck_omap36xx,
+ &dpll3_m3x2_ck_omap36xx,
+ &dpll4_m6x2_ck_omap36xx,
+ &dpll4_m2x2_ck_omap36xx,
+ &dpll4_m5x2_ck_omap36xx,
+ &dpll4_ck_omap36xx,
+ NULL,
+};
+
+static const char *enable_init_clks[] = {
+ "sdrc_ick",
+ "gpmc_fck",
+ "omapctrl_ick",
+};
+
+static void __init omap3_clk_legacy_common_init(void)
+{
+ omap2_clk_disable_autoidle_all();
+
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
+ (clk_get_rate(osc_sys_ck.clk) / 1000000),
+ (clk_get_rate(osc_sys_ck.clk) / 100000) % 10,
+ (clk_get_rate(core_ck.clk) / 1000000),
+ (clk_get_rate(arm_fck.clk) / 1000000));
+}
+
+int __init omap3430es1_clk_legacy_init(void)
+{
+ int r;
+
+ r = ti_clk_register_legacy_clks(omap3430es1_clks);
+ r |= ti_clk_register_legacy_clks(omap34xx_omap36xx_clks);
+ r |= ti_clk_register_legacy_clks(omap3xxx_clks);
+
+ omap3_clk_legacy_common_init();
+
+ return r;
+}
+
+int __init omap3430_clk_legacy_init(void)
+{
+ int r;
+
+ r = ti_clk_register_legacy_clks(omap34xx_omap36xx_clks);
+ r |= ti_clk_register_legacy_clks(omap36xx_omap3430es2plus_clks);
+ r |= ti_clk_register_legacy_clks(omap36xx_am35xx_omap3430es2plus_clks);
+ r |= ti_clk_register_legacy_clks(omap3xxx_clks);
+
+ omap3_clk_legacy_common_init();
+ omap3_clk_lock_dpll5();
+
+ return r;
+}
+
+int __init omap36xx_clk_legacy_init(void)
+{
+ int r;
+
+ ti_clk_patch_legacy_clks(omap36xx_clk_patches);
+ r = ti_clk_register_legacy_clks(omap36xx_clks);
+ r |= ti_clk_register_legacy_clks(omap36xx_omap3430es2plus_clks);
+ r |= ti_clk_register_legacy_clks(omap34xx_omap36xx_clks);
+ r |= ti_clk_register_legacy_clks(omap36xx_am35xx_omap3430es2plus_clks);
+ r |= ti_clk_register_legacy_clks(omap3xxx_clks);
+
+ omap3_clk_legacy_common_init();
+ omap3_clk_lock_dpll5();
+
+ return r;
+}
+
+int __init am35xx_clk_legacy_init(void)
+{
+ int r;
+
+ r = ti_clk_register_legacy_clks(am35xx_clks);
+ r |= ti_clk_register_legacy_clks(omap36xx_am35xx_omap3430es2plus_clks);
+ r |= ti_clk_register_legacy_clks(omap3xxx_clks);
+
+ omap3_clk_legacy_common_init();
+ omap3_clk_lock_dpll5();
+
+ return r;
+}
diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c
index 0d1750a8aea40d..383a06e49b09db 100644
--- a/drivers/clk/ti/clk-3xxx.c
+++ b/drivers/clk/ti/clk-3xxx.c
@@ -327,7 +327,6 @@ enum {
OMAP3_SOC_OMAP3430_ES1,
OMAP3_SOC_OMAP3430_ES2_PLUS,
OMAP3_SOC_OMAP3630,
- OMAP3_SOC_TI81XX,
};
static int __init omap3xxx_dt_clk_init(int soc_type)
@@ -370,7 +369,7 @@ static int __init omap3xxx_dt_clk_init(int soc_type)
(clk_get_rate(clk_get_sys(NULL, "core_ck")) / 1000000),
(clk_get_rate(clk_get_sys(NULL, "arm_fck")) / 1000000));
- if (soc_type != OMAP3_SOC_TI81XX && soc_type != OMAP3_SOC_OMAP3430_ES1)
+ if (soc_type != OMAP3_SOC_OMAP3430_ES1)
omap3_clk_lock_dpll5();
return 0;
@@ -390,8 +389,3 @@ int __init am35xx_dt_clk_init(void)
{
return omap3xxx_dt_clk_init(OMAP3_SOC_AM35XX);
}
-
-int __init ti81xx_dt_clk_init(void)
-{
- return omap3xxx_dt_clk_init(OMAP3_SOC_TI81XX);
-}
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index 02517a8206bda8..4f4c87751db521 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -12,7 +12,7 @@
#include
#include
-#include
+#include
#include
#include
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c
index 5e183993e3ec56..14160b2235480f 100644
--- a/drivers/clk/ti/clk-54xx.c
+++ b/drivers/clk/ti/clk-54xx.c
@@ -12,7 +12,7 @@
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index 62ac8f6e480c61..ee32f4deebf402 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -12,7 +12,7 @@
#include
#include
-#include
+#include
#include
#include
diff --git a/drivers/clk/ti/clk-816x.c b/drivers/clk/ti/clk-816x.c
new file mode 100644
index 00000000000000..9451e651a1ff74
--- /dev/null
+++ b/drivers/clk/ti/clk-816x.c
@@ -0,0 +1,53 @@
+/*
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+
+static struct ti_dt_clk dm816x_clks[] = {
+ DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"),
+ DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
+ DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
+ DT_CLK(NULL, "mpu_ck", "mpu_ck"),
+ DT_CLK(NULL, "timer1_fck", "timer1_fck"),
+ DT_CLK(NULL, "timer2_fck", "timer2_fck"),
+ DT_CLK(NULL, "timer3_fck", "timer3_fck"),
+ DT_CLK(NULL, "timer4_fck", "timer4_fck"),
+ DT_CLK(NULL, "timer5_fck", "timer5_fck"),
+ DT_CLK(NULL, "timer6_fck", "timer6_fck"),
+ DT_CLK(NULL, "timer7_fck", "timer7_fck"),
+ DT_CLK(NULL, "sysclk4_ck", "sysclk4_ck"),
+ DT_CLK(NULL, "sysclk5_ck", "sysclk5_ck"),
+ DT_CLK(NULL, "sysclk6_ck", "sysclk6_ck"),
+ DT_CLK(NULL, "sysclk10_ck", "sysclk10_ck"),
+ DT_CLK(NULL, "sysclk18_ck", "sysclk18_ck"),
+ DT_CLK(NULL, "sysclk24_ck", "sysclk24_ck"),
+ DT_CLK("4a100000.ethernet", "sysclk24_ck", "sysclk24_ck"),
+ { .node_name = NULL },
+};
+
+static const char *enable_init_clks[] = {
+ "ddr_pll_clk1",
+ "ddr_pll_clk2",
+ "ddr_pll_clk3",
+};
+
+int __init ti81xx_dt_clk_init(void)
+{
+ ti_dt_clocks_register(dm816x_clks);
+ omap2_clk_disable_autoidle_all();
+ omap2_clk_enable_init_clocks(enable_init_clks,
+ ARRAY_SIZE(enable_init_clks));
+
+ return 0;
+}
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 337abe5909e1f2..e22b95646e09a8 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -22,6 +22,8 @@
#include
#include
+#include "clock.h"
+
#undef pr_fmt
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -183,3 +185,128 @@ void ti_dt_clk_init_retry_clks(void)
retries--;
}
}
+
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
+void __init ti_clk_patch_legacy_clks(struct ti_clk **patch)
+{
+ while (*patch) {
+ memcpy((*patch)->patch, *patch, sizeof(**patch));
+ patch++;
+ }
+}
+
+struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
+{
+ struct clk *clk;
+ struct ti_clk_fixed *fixed;
+ struct ti_clk_fixed_factor *fixed_factor;
+ struct clk_hw *clk_hw;
+
+ if (setup->clk)
+ return setup->clk;
+
+ switch (setup->type) {
+ case TI_CLK_FIXED:
+ fixed = setup->data;
+
+ clk = clk_register_fixed_rate(NULL, setup->name, NULL,
+ CLK_IS_ROOT, fixed->frequency);
+ break;
+ case TI_CLK_MUX:
+ clk = ti_clk_register_mux(setup);
+ break;
+ case TI_CLK_DIVIDER:
+ clk = ti_clk_register_divider(setup);
+ break;
+ case TI_CLK_COMPOSITE:
+ clk = ti_clk_register_composite(setup);
+ break;
+ case TI_CLK_FIXED_FACTOR:
+ fixed_factor = setup->data;
+
+ clk = clk_register_fixed_factor(NULL, setup->name,
+ fixed_factor->parent,
+ 0, fixed_factor->mult,
+ fixed_factor->div);
+ break;
+ case TI_CLK_GATE:
+ clk = ti_clk_register_gate(setup);
+ break;
+ case TI_CLK_DPLL:
+ clk = ti_clk_register_dpll(setup);
+ break;
+ default:
+ pr_err("bad type for %s!\n", setup->name);
+ clk = ERR_PTR(-EINVAL);
+ }
+
+ if (!IS_ERR(clk)) {
+ setup->clk = clk;
+ if (setup->clkdm_name) {
+ if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+ pr_warn("can't setup clkdm for basic clk %s\n",
+ setup->name);
+ } else {
+ clk_hw = __clk_get_hw(clk);
+ to_clk_hw_omap(clk_hw)->clkdm_name =
+ setup->clkdm_name;
+ omap2_init_clk_clkdm(clk_hw);
+ }
+ }
+ }
+
+ return clk;
+}
+
+int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
+{
+ struct clk *clk;
+ bool retry;
+ struct ti_clk_alias *retry_clk;
+ struct ti_clk_alias *tmp;
+
+ while (clks->clk) {
+ clk = ti_clk_register_clk(clks->clk);
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) == -EAGAIN) {
+ list_add(&clks->link, &retry_list);
+ } else {
+ pr_err("register for %s failed: %ld\n",
+ clks->clk->name, PTR_ERR(clk));
+ return PTR_ERR(clk);
+ }
+ } else {
+ clks->lk.clk = clk;
+ clkdev_add(&clks->lk);
+ }
+ clks++;
+ }
+
+ retry = true;
+
+ while (!list_empty(&retry_list) && retry) {
+ retry = false;
+ list_for_each_entry_safe(retry_clk, tmp, &retry_list, link) {
+ pr_debug("retry-init: %s\n", retry_clk->clk->name);
+ clk = ti_clk_register_clk(retry_clk->clk);
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) == -EAGAIN) {
+ continue;
+ } else {
+ pr_err("register for %s failed: %ld\n",
+ retry_clk->clk->name,
+ PTR_ERR(clk));
+ return PTR_ERR(clk);
+ }
+ } else {
+ retry = true;
+ retry_clk->lk.clk = clk;
+ clkdev_add(&retry_clk->lk);
+ list_del(&retry_clk->link);
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
new file mode 100644
index 00000000000000..404158d2d7f880
--- /dev/null
+++ b/drivers/clk/ti/clock.h
@@ -0,0 +1,172 @@
+/*
+ * TI Clock driver internal definitions
+ *
+ * Copyright (C) 2014 Texas Instruments, Inc
+ * Tero Kristo (t-kristo@ti.com)
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DRIVERS_CLK_TI_CLOCK__
+#define __DRIVERS_CLK_TI_CLOCK__
+
+enum {
+ TI_CLK_FIXED,
+ TI_CLK_MUX,
+ TI_CLK_DIVIDER,
+ TI_CLK_COMPOSITE,
+ TI_CLK_FIXED_FACTOR,
+ TI_CLK_GATE,
+ TI_CLK_DPLL,
+};
+
+/* Global flags */
+#define CLKF_INDEX_POWER_OF_TWO (1 << 0)
+#define CLKF_INDEX_STARTS_AT_ONE (1 << 1)
+#define CLKF_SET_RATE_PARENT (1 << 2)
+#define CLKF_OMAP3 (1 << 3)
+#define CLKF_AM35XX (1 << 4)
+
+/* Gate flags */
+#define CLKF_SET_BIT_TO_DISABLE (1 << 5)
+#define CLKF_INTERFACE (1 << 6)
+#define CLKF_SSI (1 << 7)
+#define CLKF_DSS (1 << 8)
+#define CLKF_HSOTGUSB (1 << 9)
+#define CLKF_WAIT (1 << 10)
+#define CLKF_NO_WAIT (1 << 11)
+#define CLKF_HSDIV (1 << 12)
+#define CLKF_CLKDM (1 << 13)
+
+/* DPLL flags */
+#define CLKF_LOW_POWER_STOP (1 << 5)
+#define CLKF_LOCK (1 << 6)
+#define CLKF_LOW_POWER_BYPASS (1 << 7)
+#define CLKF_PER (1 << 8)
+#define CLKF_CORE (1 << 9)
+#define CLKF_J_TYPE (1 << 10)
+
+#define CLK(dev, con, ck) \
+ { \
+ .lk = { \
+ .dev_id = dev, \
+ .con_id = con, \
+ }, \
+ .clk = ck, \
+ }
+
+struct ti_clk {
+ const char *name;
+ const char *clkdm_name;
+ int type;
+ void *data;
+ struct ti_clk *patch;
+ struct clk *clk;
+};
+
+struct ti_clk_alias {
+ struct ti_clk *clk;
+ struct clk_lookup lk;
+ struct list_head link;
+};
+
+struct ti_clk_fixed {
+ u32 frequency;
+ u16 flags;
+};
+
+struct ti_clk_mux {
+ u8 bit_shift;
+ int num_parents;
+ u16 reg;
+ u8 module;
+ const char **parents;
+ u16 flags;
+};
+
+struct ti_clk_divider {
+ const char *parent;
+ u8 bit_shift;
+ u16 max_div;
+ u16 reg;
+ u8 module;
+ int *dividers;
+ int num_dividers;
+ u16 flags;
+};
+
+struct ti_clk_fixed_factor {
+ const char *parent;
+ u16 div;
+ u16 mult;
+ u16 flags;
+};
+
+struct ti_clk_gate {
+ const char *parent;
+ u8 bit_shift;
+ u16 reg;
+ u8 module;
+ u16 flags;
+};
+
+struct ti_clk_composite {
+ struct ti_clk_divider *divider;
+ struct ti_clk_mux *mux;
+ struct ti_clk_gate *gate;
+ u16 flags;
+};
+
+struct ti_clk_clkdm_gate {
+ const char *parent;
+ u16 flags;
+};
+
+struct ti_clk_dpll {
+ int num_parents;
+ u16 control_reg;
+ u16 idlest_reg;
+ u16 autoidle_reg;
+ u16 mult_div1_reg;
+ u8 module;
+ const char **parents;
+ u16 flags;
+ u8 modes;
+ u32 mult_mask;
+ u32 div1_mask;
+ u32 enable_mask;
+ u32 autoidle_mask;
+ u32 freqsel_mask;
+ u32 idlest_mask;
+ u32 dco_mask;
+ u32 sddiv_mask;
+ u16 max_multiplier;
+ u16 max_divider;
+ u8 min_divider;
+ u8 auto_recal_bit;
+ u8 recal_en_bit;
+ u8 recal_st_bit;
+};
+
+struct clk *ti_clk_register_gate(struct ti_clk *setup);
+struct clk *ti_clk_register_interface(struct ti_clk *setup);
+struct clk *ti_clk_register_mux(struct ti_clk *setup);
+struct clk *ti_clk_register_divider(struct ti_clk *setup);
+struct clk *ti_clk_register_composite(struct ti_clk *setup);
+struct clk *ti_clk_register_dpll(struct ti_clk *setup);
+
+struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup);
+struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
+struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
+
+void ti_clk_patch_legacy_clks(struct ti_clk **patch);
+struct clk *ti_clk_register_clk(struct ti_clk *setup);
+int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
+
+#endif
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index 19d8980ba458ef..3654f61912ebb7 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -23,6 +23,8 @@
#include
#include
+#include "clock.h"
+
#undef pr_fmt
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -116,8 +118,46 @@ static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx)
#define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw)
-static void __init ti_clk_register_composite(struct clk_hw *hw,
- struct device_node *node)
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
+struct clk *ti_clk_register_composite(struct ti_clk *setup)
+{
+ struct ti_clk_composite *comp;
+ struct clk_hw *gate;
+ struct clk_hw *mux;
+ struct clk_hw *div;
+ int num_parents = 1;
+ const char **parent_names = NULL;
+ struct clk *clk;
+
+ comp = setup->data;
+
+ div = ti_clk_build_component_div(comp->divider);
+ gate = ti_clk_build_component_gate(comp->gate);
+ mux = ti_clk_build_component_mux(comp->mux);
+
+ if (div)
+ parent_names = &comp->divider->parent;
+
+ if (gate)
+ parent_names = &comp->gate->parent;
+
+ if (mux) {
+ num_parents = comp->mux->num_parents;
+ parent_names = comp->mux->parents;
+ }
+
+ clk = clk_register_composite(NULL, setup->name,
+ parent_names, num_parents, mux,
+ &ti_clk_mux_ops, div,
+ &ti_composite_divider_ops, gate,
+ &ti_composite_gate_ops, 0);
+
+ return clk;
+}
+#endif
+
+static void __init _register_composite(struct clk_hw *hw,
+ struct device_node *node)
{
struct clk *clk;
struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw);
@@ -136,7 +176,7 @@ static void __init ti_clk_register_composite(struct clk_hw *hw,
pr_debug("component %s not ready for %s, retry\n",
cclk->comp_nodes[i]->name, node->name);
if (!ti_clk_retry_init(node, hw,
- ti_clk_register_composite))
+ _register_composite))
return;
goto cleanup;
@@ -216,7 +256,7 @@ static void __init of_ti_composite_clk_setup(struct device_node *node)
for (i = 0; i < num_clks; i++)
cclk->comp_nodes[i] = _get_component_node(node, i);
- ti_clk_register_composite(&cclk->hw, node);
+ _register_composite(&cclk->hw, node);
}
CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
of_ti_composite_clk_setup);
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index bff2b5b8ff598b..6211893c098066 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -21,6 +21,7 @@
#include
#include
#include
+#include "clock.h"
#undef pr_fmt
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -300,6 +301,134 @@ static struct clk *_register_divider(struct device *dev, const char *name,
return clk;
}
+static struct clk_div_table *
+_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
+{
+ int valid_div = 0;
+ struct clk_div_table *table;
+ int i;
+ int div;
+ u32 val;
+ u8 flags;
+
+ if (!setup->num_dividers) {
+ /* Clk divider table not provided, determine min/max divs */
+ flags = setup->flags;
+
+ if (flags & CLKF_INDEX_STARTS_AT_ONE)
+ val = 1;
+ else
+ val = 0;
+
+ div = 1;
+
+ while (div < setup->max_div) {
+ if (flags & CLKF_INDEX_POWER_OF_TWO)
+ div <<= 1;
+ else
+ div++;
+ val++;
+ }
+
+ *width = fls(val);
+
+ return NULL;
+ }
+
+ for (i = 0; i < setup->num_dividers; i++)
+ if (setup->dividers[i])
+ valid_div++;
+
+ table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+
+ valid_div = 0;
+ *width = 0;
+
+ for (i = 0; i < setup->num_dividers; i++)
+ if (setup->dividers[i]) {
+ table[valid_div].div = setup->dividers[i];
+ table[valid_div].val = i;
+ valid_div++;
+ *width = i;
+ }
+
+ *width = fls(*width);
+
+ return table;
+}
+
+struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
+{
+ struct clk_divider *div;
+ struct clk_omap_reg *reg;
+
+ if (!setup)
+ return NULL;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ reg = (struct clk_omap_reg *)&div->reg;
+ reg->index = setup->module;
+ reg->offset = setup->reg;
+
+ if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
+ div->flags |= CLK_DIVIDER_ONE_BASED;
+
+ if (setup->flags & CLKF_INDEX_POWER_OF_TWO)
+ div->flags |= CLK_DIVIDER_POWER_OF_TWO;
+
+ div->table = _get_div_table_from_setup(setup, &div->width);
+
+ div->shift = setup->bit_shift;
+
+ return &div->hw;
+}
+
+struct clk *ti_clk_register_divider(struct ti_clk *setup)
+{
+ struct ti_clk_divider *div;
+ struct clk_omap_reg *reg_setup;
+ u32 reg;
+ u8 width;
+ u32 flags = 0;
+ u8 div_flags = 0;
+ struct clk_div_table *table;
+ struct clk *clk;
+
+ div = setup->data;
+
+ reg_setup = (struct clk_omap_reg *)®
+
+ reg_setup->index = div->module;
+ reg_setup->offset = div->reg;
+
+ if (div->flags & CLKF_INDEX_STARTS_AT_ONE)
+ div_flags |= CLK_DIVIDER_ONE_BASED;
+
+ if (div->flags & CLKF_INDEX_POWER_OF_TWO)
+ div_flags |= CLK_DIVIDER_POWER_OF_TWO;
+
+ if (div->flags & CLKF_SET_RATE_PARENT)
+ flags |= CLK_SET_RATE_PARENT;
+
+ table = _get_div_table_from_setup(div, &width);
+ if (IS_ERR(table))
+ return (struct clk *)table;
+
+ clk = _register_divider(NULL, setup->name, div->parent,
+ flags, (void __iomem *)reg, div->bit_shift,
+ width, div_flags, table, NULL);
+
+ if (IS_ERR(clk))
+ kfree(table);
+
+ return clk;
+}
+
static struct clk_div_table *
__init ti_clk_get_div_table(struct device_node *node)
{
@@ -455,7 +584,8 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
goto cleanup;
clk = _register_divider(NULL, node->name, parent_name, flags, reg,
- shift, width, clk_divider_flags, table, NULL);
+ shift, width, clk_divider_flags, table,
+ NULL);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 85ac0dd501dea5..81dc4698dc4174 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -21,6 +21,7 @@
#include
#include
#include
+#include "clock.h"
#undef pr_fmt
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -130,7 +131,7 @@ static const struct clk_ops dpll_x2_ck_ops = {
};
/**
- * ti_clk_register_dpll - low level registration of a DPLL clock
+ * _register_dpll - low level registration of a DPLL clock
* @hw: hardware clock definition for the clock
* @node: device node for the clock
*
@@ -138,8 +139,8 @@ static const struct clk_ops dpll_x2_ck_ops = {
* clk-bypass is missing), the clock is added to retry list and
* the initialization is retried on later stage.
*/
-static void __init ti_clk_register_dpll(struct clk_hw *hw,
- struct device_node *node)
+static void __init _register_dpll(struct clk_hw *hw,
+ struct device_node *node)
{
struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
struct dpll_data *dd = clk_hw->dpll_data;
@@ -151,7 +152,7 @@ static void __init ti_clk_register_dpll(struct clk_hw *hw,
if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) {
pr_debug("clk-ref or clk-bypass missing for %s, retry later\n",
node->name);
- if (!ti_clk_retry_init(node, hw, ti_clk_register_dpll))
+ if (!ti_clk_retry_init(node, hw, _register_dpll))
return;
goto cleanup;
@@ -175,20 +176,118 @@ static void __init ti_clk_register_dpll(struct clk_hw *hw,
kfree(clk_hw);
}
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
+void __iomem *_get_reg(u8 module, u16 offset)
+{
+ u32 reg;
+ struct clk_omap_reg *reg_setup;
+
+ reg_setup = (struct clk_omap_reg *)®
+
+ reg_setup->index = module;
+ reg_setup->offset = offset;
+
+ return (void __iomem *)reg;
+}
+
+struct clk *ti_clk_register_dpll(struct ti_clk *setup)
+{
+ struct clk_hw_omap *clk_hw;
+ struct clk_init_data init = { NULL };
+ struct dpll_data *dd;
+ struct clk *clk;
+ struct ti_clk_dpll *dpll;
+ const struct clk_ops *ops = &omap3_dpll_ck_ops;
+ struct clk *clk_ref;
+ struct clk *clk_bypass;
+
+ dpll = setup->data;
+
+ if (dpll->num_parents < 2)
+ return ERR_PTR(-EINVAL);
+
+ clk_ref = clk_get_sys(NULL, dpll->parents[0]);
+ clk_bypass = clk_get_sys(NULL, dpll->parents[1]);
+
+ if (IS_ERR_OR_NULL(clk_ref) || IS_ERR_OR_NULL(clk_bypass))
+ return ERR_PTR(-EAGAIN);
+
+ dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+ if (!dd || !clk_hw) {
+ clk = ERR_PTR(-ENOMEM);
+ goto cleanup;
+ }
+
+ clk_hw->dpll_data = dd;
+ clk_hw->ops = &clkhwops_omap3_dpll;
+ clk_hw->hw.init = &init;
+ clk_hw->flags = MEMMAP_ADDRESSING;
+
+ init.name = setup->name;
+ init.ops = ops;
+
+ init.num_parents = dpll->num_parents;
+ init.parent_names = dpll->parents;
+
+ dd->control_reg = _get_reg(dpll->module, dpll->control_reg);
+ dd->idlest_reg = _get_reg(dpll->module, dpll->idlest_reg);
+ dd->mult_div1_reg = _get_reg(dpll->module, dpll->mult_div1_reg);
+ dd->autoidle_reg = _get_reg(dpll->module, dpll->autoidle_reg);
+
+ dd->modes = dpll->modes;
+ dd->div1_mask = dpll->div1_mask;
+ dd->idlest_mask = dpll->idlest_mask;
+ dd->mult_mask = dpll->mult_mask;
+ dd->autoidle_mask = dpll->autoidle_mask;
+ dd->enable_mask = dpll->enable_mask;
+ dd->sddiv_mask = dpll->sddiv_mask;
+ dd->dco_mask = dpll->dco_mask;
+ dd->max_divider = dpll->max_divider;
+ dd->min_divider = dpll->min_divider;
+ dd->max_multiplier = dpll->max_multiplier;
+ dd->auto_recal_bit = dpll->auto_recal_bit;
+ dd->recal_en_bit = dpll->recal_en_bit;
+ dd->recal_st_bit = dpll->recal_st_bit;
+
+ dd->clk_ref = clk_ref;
+ dd->clk_bypass = clk_bypass;
+
+ if (dpll->flags & CLKF_CORE)
+ ops = &omap3_dpll_core_ck_ops;
+
+ if (dpll->flags & CLKF_PER)
+ ops = &omap3_dpll_per_ck_ops;
+
+ if (dpll->flags & CLKF_J_TYPE)
+ dd->flags |= DPLL_J_TYPE;
+
+ clk = clk_register(NULL, &clk_hw->hw);
+
+ if (!IS_ERR(clk))
+ return clk;
+
+cleanup:
+ kfree(dd);
+ kfree(clk_hw);
+ return clk;
+}
+#endif
+
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX) || \
defined(CONFIG_SOC_AM43XX)
/**
- * ti_clk_register_dpll_x2 - Registers a DPLLx2 clock
+ * _register_dpll_x2 - Registers a DPLLx2 clock
* @node: device node for this clock
* @ops: clk_ops for this clock
* @hw_ops: clk_hw_ops for this clock
*
* Initializes a DPLL x 2 clock from device tree data.
*/
-static void ti_clk_register_dpll_x2(struct device_node *node,
- const struct clk_ops *ops,
- const struct clk_hw_omap_ops *hw_ops)
+static void _register_dpll_x2(struct device_node *node,
+ const struct clk_ops *ops,
+ const struct clk_hw_omap_ops *hw_ops)
{
struct clk *clk;
struct clk_init_data init = { NULL };
@@ -318,7 +417,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
if (dpll_mode)
dd->modes = dpll_mode;
- ti_clk_register_dpll(&clk_hw->hw, node);
+ _register_dpll(&clk_hw->hw, node);
return;
cleanup:
@@ -332,7 +431,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
defined(CONFIG_SOC_DRA7XX)
static void __init of_ti_omap4_dpll_x2_setup(struct device_node *node)
{
- ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx);
+ _register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx);
}
CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
of_ti_omap4_dpll_x2_setup);
@@ -341,7 +440,7 @@ CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
static void __init of_ti_am3_dpll_x2_setup(struct device_node *node)
{
- ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, NULL);
+ _register_dpll_x2(node, &dpll_x2_ck_ops, NULL);
}
CLK_OF_DECLARE(ti_am3_dpll_x2_clock, "ti,am3-dpll-x2-clock",
of_ti_am3_dpll_x2_setup);
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
new file mode 100644
index 00000000000000..6ef89639a9f68b
--- /dev/null
+++ b/drivers/clk/ti/fapll.c
@@ -0,0 +1,410 @@
+/*
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* FAPLL Control Register PLL_CTRL */
+#define FAPLL_MAIN_LOCK BIT(7)
+#define FAPLL_MAIN_PLLEN BIT(3)
+#define FAPLL_MAIN_BP BIT(2)
+#define FAPLL_MAIN_LOC_CTL BIT(0)
+
+/* FAPLL powerdown register PWD */
+#define FAPLL_PWD_OFFSET 4
+
+#define MAX_FAPLL_OUTPUTS 7
+#define FAPLL_MAX_RETRIES 1000
+
+#define to_fapll(_hw) container_of(_hw, struct fapll_data, hw)
+#define to_synth(_hw) container_of(_hw, struct fapll_synth, hw)
+
+/* The bypass bit is inverted on the ddr_pll.. */
+#define fapll_is_ddr_pll(va) (((u32)(va) & 0xffff) == 0x0440)
+
+/*
+ * The audio_pll_clk1 input is hard wired to the 27MHz bypass clock,
+ * and the audio_pll_clk1 synthesizer is hardwared to 32KiHz output.
+ */
+#define is_ddr_pll_clk1(va) (((u32)(va) & 0xffff) == 0x044c)
+#define is_audio_pll_clk1(va) (((u32)(va) & 0xffff) == 0x04a8)
+
+/* Synthesizer divider register */
+#define SYNTH_LDMDIV1 BIT(8)
+
+/* Synthesizer frequency register */
+#define SYNTH_LDFREQ BIT(31)
+
+struct fapll_data {
+ struct clk_hw hw;
+ void __iomem *base;
+ const char *name;
+ struct clk *clk_ref;
+ struct clk *clk_bypass;
+ struct clk_onecell_data outputs;
+ bool bypass_bit_inverted;
+};
+
+struct fapll_synth {
+ struct clk_hw hw;
+ struct fapll_data *fd;
+ int index;
+ void __iomem *freq;
+ void __iomem *div;
+ const char *name;
+ struct clk *clk_pll;
+};
+
+static bool ti_fapll_clock_is_bypass(struct fapll_data *fd)
+{
+ u32 v = readl_relaxed(fd->base);
+
+ if (fd->bypass_bit_inverted)
+ return !(v & FAPLL_MAIN_BP);
+ else
+ return !!(v & FAPLL_MAIN_BP);
+}
+
+static int ti_fapll_enable(struct clk_hw *hw)
+{
+ struct fapll_data *fd = to_fapll(hw);
+ u32 v = readl_relaxed(fd->base);
+
+ v |= (1 << FAPLL_MAIN_PLLEN);
+ writel_relaxed(v, fd->base);
+
+ return 0;
+}
+
+static void ti_fapll_disable(struct clk_hw *hw)
+{
+ struct fapll_data *fd = to_fapll(hw);
+ u32 v = readl_relaxed(fd->base);
+
+ v &= ~(1 << FAPLL_MAIN_PLLEN);
+ writel_relaxed(v, fd->base);
+}
+
+static int ti_fapll_is_enabled(struct clk_hw *hw)
+{
+ struct fapll_data *fd = to_fapll(hw);
+ u32 v = readl_relaxed(fd->base);
+
+ return v & (1 << FAPLL_MAIN_PLLEN);
+}
+
+static unsigned long ti_fapll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct fapll_data *fd = to_fapll(hw);
+ u32 fapll_n, fapll_p, v;
+ long long rate;
+
+ if (ti_fapll_clock_is_bypass(fd))
+ return parent_rate;
+
+ rate = parent_rate;
+
+ /* PLL pre-divider is P and multiplier is N */
+ v = readl_relaxed(fd->base);
+ fapll_p = (v >> 8) & 0xff;
+ if (fapll_p)
+ do_div(rate, fapll_p);
+ fapll_n = v >> 16;
+ if (fapll_n)
+ rate *= fapll_n;
+
+ return rate;
+}
+
+static u8 ti_fapll_get_parent(struct clk_hw *hw)
+{
+ struct fapll_data *fd = to_fapll(hw);
+
+ if (ti_fapll_clock_is_bypass(fd))
+ return 1;
+
+ return 0;
+}
+
+static struct clk_ops ti_fapll_ops = {
+ .enable = ti_fapll_enable,
+ .disable = ti_fapll_disable,
+ .is_enabled = ti_fapll_is_enabled,
+ .recalc_rate = ti_fapll_recalc_rate,
+ .get_parent = ti_fapll_get_parent,
+};
+
+static int ti_fapll_synth_enable(struct clk_hw *hw)
+{
+ struct fapll_synth *synth = to_synth(hw);
+ u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET);
+
+ v &= ~(1 << synth->index);
+ writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET);
+
+ return 0;
+}
+
+static void ti_fapll_synth_disable(struct clk_hw *hw)
+{
+ struct fapll_synth *synth = to_synth(hw);
+ u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET);
+
+ v |= 1 << synth->index;
+ writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET);
+}
+
+static int ti_fapll_synth_is_enabled(struct clk_hw *hw)
+{
+ struct fapll_synth *synth = to_synth(hw);
+ u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET);
+
+ return !(v & (1 << synth->index));
+}
+
+/*
+ * See dm816x TRM chapter 1.10.3 Flying Adder PLL fore more info
+ */
+static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct fapll_synth *synth = to_synth(hw);
+ u32 synth_div_m;
+ long long rate;
+
+ /* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */
+ if (!synth->div)
+ return 32768;
+
+ /*
+ * PLL in bypass sets the synths in bypass mode too. The PLL rate
+ * can be also be set to 27MHz, so we can't use parent_rate to
+ * check for bypass mode.
+ */
+ if (ti_fapll_clock_is_bypass(synth->fd))
+ return parent_rate;
+
+ rate = parent_rate;
+
+ /*
+ * Synth frequency integer and fractional divider.
+ * Note that the phase output K is 8, so the result needs
+ * to be multiplied by 8.
+ */
+ if (synth->freq) {
+ u32 v, synth_int_div, synth_frac_div, synth_div_freq;
+
+ v = readl_relaxed(synth->freq);
+ synth_int_div = (v >> 24) & 0xf;
+ synth_frac_div = v & 0xffffff;
+ synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
+ rate *= 10000000;
+ do_div(rate, synth_div_freq);
+ rate *= 8;
+ }
+
+ /* Synth ost-divider M */
+ synth_div_m = readl_relaxed(synth->div) & 0xff;
+ do_div(rate, synth_div_m);
+
+ return rate;
+}
+
+static struct clk_ops ti_fapll_synt_ops = {
+ .enable = ti_fapll_synth_enable,
+ .disable = ti_fapll_synth_disable,
+ .is_enabled = ti_fapll_synth_is_enabled,
+ .recalc_rate = ti_fapll_synth_recalc_rate,
+};
+
+static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
+ void __iomem *freq,
+ void __iomem *div,
+ int index,
+ const char *name,
+ const char *parent,
+ struct clk *pll_clk)
+{
+ struct clk_init_data *init;
+ struct fapll_synth *synth;
+
+ init = kzalloc(sizeof(*init), GFP_KERNEL);
+ if (!init)
+ return ERR_PTR(-ENOMEM);
+
+ init->ops = &ti_fapll_synt_ops;
+ init->name = name;
+ init->parent_names = &parent;
+ init->num_parents = 1;
+
+ synth = kzalloc(sizeof(*synth), GFP_KERNEL);
+ if (!synth)
+ goto free;
+
+ synth->fd = fd;
+ synth->index = index;
+ synth->freq = freq;
+ synth->div = div;
+ synth->name = name;
+ synth->hw.init = init;
+ synth->clk_pll = pll_clk;
+
+ return clk_register(NULL, &synth->hw);
+
+free:
+ kfree(synth);
+ kfree(init);
+
+ return ERR_PTR(-ENOMEM);
+}
+
+static void __init ti_fapll_setup(struct device_node *node)
+{
+ struct fapll_data *fd;
+ struct clk_init_data *init = NULL;
+ const char *parent_name[2];
+ struct clk *pll_clk;
+ int i;
+
+ fd = kzalloc(sizeof(*fd), GFP_KERNEL);
+ if (!fd)
+ return;
+
+ fd->outputs.clks = kzalloc(sizeof(struct clk *) *
+ MAX_FAPLL_OUTPUTS + 1,
+ GFP_KERNEL);
+ if (!fd->outputs.clks)
+ goto free;
+
+ init = kzalloc(sizeof(*init), GFP_KERNEL);
+ if (!init)
+ goto free;
+
+ init->ops = &ti_fapll_ops;
+ init->name = node->name;
+
+ init->num_parents = of_clk_get_parent_count(node);
+ if (init->num_parents != 2) {
+ pr_err("%s must have two parents\n", node->name);
+ goto free;
+ }
+
+ parent_name[0] = of_clk_get_parent_name(node, 0);
+ parent_name[1] = of_clk_get_parent_name(node, 1);
+ init->parent_names = parent_name;
+
+ fd->clk_ref = of_clk_get(node, 0);
+ if (IS_ERR(fd->clk_ref)) {
+ pr_err("%s could not get clk_ref\n", node->name);
+ goto free;
+ }
+
+ fd->clk_bypass = of_clk_get(node, 1);
+ if (IS_ERR(fd->clk_bypass)) {
+ pr_err("%s could not get clk_bypass\n", node->name);
+ goto free;
+ }
+
+ fd->base = of_iomap(node, 0);
+ if (!fd->base) {
+ pr_err("%s could not get IO base\n", node->name);
+ goto free;
+ }
+
+ if (fapll_is_ddr_pll(fd->base))
+ fd->bypass_bit_inverted = true;
+
+ fd->name = node->name;
+ fd->hw.init = init;
+
+ /* Register the parent PLL */
+ pll_clk = clk_register(NULL, &fd->hw);
+ if (IS_ERR(pll_clk))
+ goto unmap;
+
+ fd->outputs.clks[0] = pll_clk;
+ fd->outputs.clk_num++;
+
+ /*
+ * Set up the child synthesizers starting at index 1 as the
+ * PLL output is at index 0. We need to check the clock-indices
+ * for numbering in case there are holes in the synth mapping,
+ * and then probe the synth register to see if it has a FREQ
+ * register available.
+ */
+ for (i = 0; i < MAX_FAPLL_OUTPUTS; i++) {
+ const char *output_name;
+ void __iomem *freq, *div;
+ struct clk *synth_clk;
+ int output_instance;
+ u32 v;
+
+ if (of_property_read_string_index(node, "clock-output-names",
+ i, &output_name))
+ continue;
+
+ if (of_property_read_u32_index(node, "clock-indices", i,
+ &output_instance))
+ output_instance = i;
+
+ freq = fd->base + (output_instance * 8);
+ div = freq + 4;
+
+ /* Check for hardwired audio_pll_clk1 */
+ if (is_audio_pll_clk1(freq)) {
+ freq = 0;
+ div = 0;
+ } else {
+ /* Does the synthesizer have a FREQ register? */
+ v = readl_relaxed(freq);
+ if (!v)
+ freq = 0;
+ }
+ synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance,
+ output_name, node->name,
+ pll_clk);
+ if (IS_ERR(synth_clk))
+ continue;
+
+ fd->outputs.clks[output_instance] = synth_clk;
+ fd->outputs.clk_num++;
+
+ clk_register_clkdev(synth_clk, output_name, NULL);
+ }
+
+ /* Register the child synthesizers as the FAPLL outputs */
+ of_clk_add_provider(node, of_clk_src_onecell_get, &fd->outputs);
+ /* Add clock alias for the outputs */
+
+ kfree(init);
+
+ return;
+
+unmap:
+ iounmap(fd->base);
+free:
+ if (fd->clk_bypass)
+ clk_put(fd->clk_bypass);
+ if (fd->clk_ref)
+ clk_put(fd->clk_ref);
+ kfree(fd->outputs.clks);
+ kfree(fd);
+ kfree(init);
+}
+
+CLK_OF_DECLARE(ti_fapll_clock, "ti,dm816-fapll-clock", ti_fapll_setup);
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index b326d2797feb23..d493307b73f42b 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -22,6 +22,8 @@
#include
#include
+#include "clock.h"
+
#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
#undef pr_fmt
@@ -90,63 +92,164 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
return ret;
}
-static void __init _of_ti_gate_clk_setup(struct device_node *node,
- const struct clk_ops *ops,
- const struct clk_hw_omap_ops *hw_ops)
+static struct clk *_register_gate(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, const struct clk_ops *ops,
+ const struct clk_hw_omap_ops *hw_ops)
{
- struct clk *clk;
struct clk_init_data init = { NULL };
struct clk_hw_omap *clk_hw;
- const char *clk_name = node->name;
- const char *parent_name;
- u32 val;
+ struct clk *clk;
clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
if (!clk_hw)
- return;
+ return ERR_PTR(-ENOMEM);
clk_hw->hw.init = &init;
- init.name = clk_name;
+ init.name = name;
init.ops = ops;
- if (ops != &omap_gate_clkdm_clk_ops) {
- clk_hw->enable_reg = ti_clk_get_reg_addr(node, 0);
- if (!clk_hw->enable_reg)
- goto cleanup;
+ clk_hw->enable_reg = reg;
+ clk_hw->enable_bit = bit_idx;
+ clk_hw->ops = hw_ops;
- if (!of_property_read_u32(node, "ti,bit-shift", &val))
- clk_hw->enable_bit = val;
+ clk_hw->flags = MEMMAP_ADDRESSING | clk_gate_flags;
+
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ init.flags = flags;
+
+ clk = clk_register(NULL, &clk_hw->hw);
+
+ if (IS_ERR(clk))
+ kfree(clk_hw);
+
+ return clk;
+}
+
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
+struct clk *ti_clk_register_gate(struct ti_clk *setup)
+{
+ const struct clk_ops *ops = &omap_gate_clk_ops;
+ const struct clk_hw_omap_ops *hw_ops = NULL;
+ u32 reg;
+ struct clk_omap_reg *reg_setup;
+ u32 flags = 0;
+ u8 clk_gate_flags = 0;
+ struct ti_clk_gate *gate;
+
+ gate = setup->data;
+
+ if (gate->flags & CLKF_INTERFACE)
+ return ti_clk_register_interface(setup);
+
+ reg_setup = (struct clk_omap_reg *)®
+
+ if (gate->flags & CLKF_SET_RATE_PARENT)
+ flags |= CLK_SET_RATE_PARENT;
+
+ if (gate->flags & CLKF_SET_BIT_TO_DISABLE)
+ clk_gate_flags |= INVERT_ENABLE;
+
+ if (gate->flags & CLKF_HSDIV) {
+ ops = &omap_gate_clk_hsdiv_restore_ops;
+ hw_ops = &clkhwops_wait;
}
- clk_hw->ops = hw_ops;
+ if (gate->flags & CLKF_DSS)
+ hw_ops = &clkhwops_omap3430es2_dss_usbhost_wait;
+
+ if (gate->flags & CLKF_WAIT)
+ hw_ops = &clkhwops_wait;
+
+ if (gate->flags & CLKF_CLKDM)
+ ops = &omap_gate_clkdm_clk_ops;
+
+ if (gate->flags & CLKF_AM35XX)
+ hw_ops = &clkhwops_am35xx_ipss_module_wait;
- clk_hw->flags = MEMMAP_ADDRESSING;
+ reg_setup->index = gate->module;
+ reg_setup->offset = gate->reg;
+
+ return _register_gate(NULL, setup->name, gate->parent, flags,
+ (void __iomem *)reg, gate->bit_shift,
+ clk_gate_flags, ops, hw_ops);
+}
+
+struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup)
+{
+ struct clk_hw_omap *gate;
+ struct clk_omap_reg *reg;
+ const struct clk_hw_omap_ops *ops = &clkhwops_wait;
+
+ if (!setup)
+ return NULL;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ reg = (struct clk_omap_reg *)&gate->enable_reg;
+ reg->index = setup->module;
+ reg->offset = setup->reg;
+
+ gate->enable_bit = setup->bit_shift;
+
+ if (setup->flags & CLKF_NO_WAIT)
+ ops = NULL;
+
+ if (setup->flags & CLKF_INTERFACE)
+ ops = &clkhwops_iclk_wait;
+
+ gate->ops = ops;
+ gate->flags = MEMMAP_ADDRESSING;
+
+ return &gate->hw;
+}
+#endif
+
+static void __init _of_ti_gate_clk_setup(struct device_node *node,
+ const struct clk_ops *ops,
+ const struct clk_hw_omap_ops *hw_ops)
+{
+ struct clk *clk;
+ const char *parent_name;
+ void __iomem *reg = NULL;
+ u8 enable_bit = 0;
+ u32 val;
+ u32 flags = 0;
+ u8 clk_gate_flags = 0;
+
+ if (ops != &omap_gate_clkdm_clk_ops) {
+ reg = ti_clk_get_reg_addr(node, 0);
+ if (!reg)
+ return;
+
+ if (!of_property_read_u32(node, "ti,bit-shift", &val))
+ enable_bit = val;
+ }
if (of_clk_get_parent_count(node) != 1) {
- pr_err("%s must have 1 parent\n", clk_name);
- goto cleanup;
+ pr_err("%s must have 1 parent\n", node->name);
+ return;
}
parent_name = of_clk_get_parent_name(node, 0);
- init.parent_names = &parent_name;
- init.num_parents = 1;
if (of_property_read_bool(node, "ti,set-rate-parent"))
- init.flags |= CLK_SET_RATE_PARENT;
+ flags |= CLK_SET_RATE_PARENT;
if (of_property_read_bool(node, "ti,set-bit-to-disable"))
- clk_hw->flags |= INVERT_ENABLE;
+ clk_gate_flags |= INVERT_ENABLE;
- clk = clk_register(NULL, &clk_hw->hw);
+ clk = _register_gate(NULL, node->name, parent_name, flags, reg,
+ enable_bit, clk_gate_flags, ops, hw_ops);
- if (!IS_ERR(clk)) {
+ if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
- return;
- }
-
-cleanup:
- kfree(clk_hw);
}
static void __init
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
index 9c3e8c4aaa40c0..265d91f071c5e3 100644
--- a/drivers/clk/ti/interface.c
+++ b/drivers/clk/ti/interface.c
@@ -20,6 +20,7 @@
#include
#include