Commit bfc7249c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-for-linus-3.19' of git://git.linaro.org/people/mike.turquette/linux

Pull clk framework updates from Mike Turquette:
 "This is much later than usual due to several last minute bugs that had
  to be addressed.  As usual the majority of changes are new drivers and
  modifications to existing drivers.  The core recieved many fixes along
  with the groundwork for several large changes coming in the future
  which will better parition clock providers from clock consumers"

* tag 'clk-for-linus-3.19' of git://git.linaro.org/people/mike.turquette/linux: (86 commits)
  clk: samsung: Fix Exynos 5420 pinctrl setup and clock disable failure due to domain being gated
  ARM: OMAP3: clock: fix boot breakage in legacy mode
  ARM: OMAP2+: clock: fix DPLL code to use new determine rate APIs
  clk: Really fix deadlock with mmap_sem
  clk: mmp: fix sparse non static symbol warning
  clk: Change clk_ops->determine_rate to return a clk_hw as the best parent
  clk: change clk_debugfs_add_file to take a struct clk_hw
  clk: Don't expose __clk_get_accuracy
  clk: Don't try to use a struct clk* after it could have been freed
  clk: Remove unused function __clk_get_prepare_count
  clk: samsung: Fix double add of syscore ops after driver rebind
  clk: samsung: exynos4: set parent of sclk_hdmiphy to hdmi
  clk: samsung: exynos4415: Fix build with PM_SLEEP disabled
  clk: samsung: remove unnecessary inclusion of header files from clk.h
  clk: samsung: remove unnecessary CONFIG_OF from clk.c
  clk: samsung: Spelling s/bwtween/between/
  clk: rockchip: Add support for the mmc clock phases using the framework
  clk: rockchip: add bindings for the mmc clocks
  clk: rockchip: rk3288 export i2s0_clkout for use in DT
  clk: rockchip: use clock ID for DMC (memory controller) on rk3288
  ...
parents a4e1328a f1e9203e
......@@ -74,7 +74,7 @@ the operations defined in clk.h:
long (*determine_rate)(struct clk_hw *hw,
unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk);
struct clk_hw **best_parent_clk);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw,
......
* Samsung Exynos4415 Clock Controller
The Exynos4415 clock controller generates and supplies clock to various
consumer devices within the Exynos4415 SoC.
Required properties:
- compatible: should be one of the following:
- "samsung,exynos4415-cmu" - for the main system clocks controller
(CMU_LEFTBUS, CMU_RIGHTBUS, CMU_TOP, CMU_CPU clock domains).
- "samsung,exynos4415-cmu-dmc" - for the Exynos4415 SoC DRAM Memory
Controller (DMC) domain clock controller.
- reg: physical base address of the controller and length of memory mapped
region.
- #clock-cells: should be 1.
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume.
All available clocks are defined as preprocessor macros in
dt-bindings/clock/exynos4415.h header and can be used in device
tree sources.
Example 1: An example of a clock controller node is listed below.
cmu: clock-controller@10030000 {
compatible = "samsung,exynos4415-cmu";
reg = <0x10030000 0x18000>;
#clock-cells = <1>;
};
cmu-dmc: clock-controller@105C0000 {
compatible = "samsung,exynos4415-cmu-dmc";
reg = <0x105C0000 0x3000>;
#clock-cells = <1>;
};
* Samsung Exynos7 Clock Controller
Exynos7 clock controller has various blocks which are instantiated
independently from the device-tree. These clock controllers
generate and supply clocks to various hardware blocks within
the SoC.
Each clock is assigned an identifier and client nodes can use
this identifier to specify the clock which they consume. All
available clocks are defined as preprocessor macros in
dt-bindings/clock/exynos7-clk.h header and can be used in
device tree sources.
External clocks:
There are several clocks that are generated outside the SoC. It
is expected that they are defined using standard clock bindings
with following clock-output-names:
- "fin_pll" - PLL input clock from XXTI
Required Properties for Clock Controller:
- compatible: clock controllers will use one of the following
compatible strings to indicate the clock controller
functionality.
- "samsung,exynos7-clock-topc"
- "samsung,exynos7-clock-top0"
- "samsung,exynos7-clock-top1"
- "samsung,exynos7-clock-ccore"
- "samsung,exynos7-clock-peric0"
- "samsung,exynos7-clock-peric1"
- "samsung,exynos7-clock-peris"
- "samsung,exynos7-clock-fsys0"
- "samsung,exynos7-clock-fsys1"
- reg: physical base address of the controller and the length of
memory mapped region.
- #clock-cells: should be 1.
- clocks: list of clock identifiers which are fed as the input to
the given clock controller. Please refer the next section to
find the input clocks for a given controller.
- clock-names: list of names of clocks which are fed as the input
to the given clock controller.
Input clocks for top0 clock controller:
- fin_pll
- dout_sclk_bus0_pll
- dout_sclk_bus1_pll
- dout_sclk_cc_pll
- dout_sclk_mfc_pll
Input clocks for top1 clock controller:
- fin_pll
- dout_sclk_bus0_pll
- dout_sclk_bus1_pll
- dout_sclk_cc_pll
- dout_sclk_mfc_pll
Input clocks for ccore clock controller:
- fin_pll
- dout_aclk_ccore_133
Input clocks for peric0 clock controller:
- fin_pll
- dout_aclk_peric0_66
- sclk_uart0
Input clocks for peric1 clock controller:
- fin_pll
- dout_aclk_peric1_66
- sclk_uart1
- sclk_uart2
- sclk_uart3
Input clocks for peris clock controller:
- fin_pll
- dout_aclk_peris_66
Input clocks for fsys0 clock controller:
- fin_pll
- dout_aclk_fsys0_200
- dout_sclk_mmc2
Input clocks for fsys1 clock controller:
- fin_pll
- dout_aclk_fsys1_200
- dout_sclk_mmc0
- dout_sclk_mmc1
* Marvell MMP2 Clock Controller
The MMP2 clock subsystem generates and supplies clock to various
controllers within the MMP2 SoC.
Required Properties:
- compatible: should be one of the following.
- "marvell,mmp2-clock" - controller compatible with MMP2 SoC.
- reg: physical base address of the clock subsystem and length of memory mapped
region. There are 3 places in SOC has clock control logic:
"mpmu", "apmu", "apbc". So three reg spaces need to be defined.
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
All these identifier could be found in <dt-bindings/clock/marvell-mmp2.h>.
* Marvell PXA168 Clock Controller
The PXA168 clock subsystem generates and supplies clock to various
controllers within the PXA168 SoC.
Required Properties:
- compatible: should be one of the following.
- "marvell,pxa168-clock" - controller compatible with PXA168 SoC.
- reg: physical base address of the clock subsystem and length of memory mapped
region. There are 3 places in SOC has clock control logic:
"mpmu", "apmu", "apbc". So three reg spaces need to be defined.
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
All these identifier could be found in <dt-bindings/clock/marvell,pxa168.h>.
* Marvell PXA910 Clock Controller
The PXA910 clock subsystem generates and supplies clock to various
controllers within the PXA910 SoC.
Required Properties:
- compatible: should be one of the following.
- "marvell,pxa910-clock" - controller compatible with PXA910 SoC.
- reg: physical base address of the clock subsystem and length of memory mapped
region. There are 4 places in SOC has clock control logic:
"mpmu", "apmu", "apbc", "apbcp". So four reg spaces need to be defined.
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
All these identifier could be found in <dt-bindings/clock/marvell-pxa910.h>.
......@@ -7,11 +7,16 @@ to 64.
Required Properties:
- compatible: Must be one of the following
- "renesas,r8a73a4-div6-clock" for R8A73A4 (R-Mobile APE6) DIV6 clocks
- "renesas,r8a7740-div6-clock" for R8A7740 (R-Mobile A1) DIV6 clocks
- "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks
- "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2) DIV6 clocks
- "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks
- "renesas,cpg-div6-clock" for generic DIV6 clocks
- reg: Base address and length of the memory resource used by the DIV6 clock
- clocks: Reference to the parent clock
- clocks: Reference to the parent clock(s); either one, four, or eight
clocks must be specified. For clocks with multiple parents, invalid
settings must be specified as "<0>".
- #clock-cells: Must be 0
- clock-output-names: The name of the clock as a free-form string
......@@ -19,10 +24,11 @@ Required Properties:
Example
-------
sd2_clk: sd2_clk@e6150078 {
compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
reg = <0 0xe6150078 0 4>;
clocks = <&pll1_div2_clk>;
sdhi2_clk: sdhi2_clk@e615007c {
compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
reg = <0 0xe615007c 0 4>;
clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
<0>, <&extal2_clk>;
#clock-cells = <0>;
clock-output-names = "sd2";
clock-output-names = "sdhi2ck";
};
......@@ -26,11 +26,11 @@ Required Properties:
must appear in the same order as the output clocks.
- #clock-cells: Must be 1
- clock-output-names: The name of the clocks as free-form strings
- renesas,clock-indices: Indices of the gate clocks into the group (0 to 31)
- clock-indices: Indices of the gate clocks into the group (0 to 31)
The clocks, clock-output-names and renesas,clock-indices properties contain one
entry per gate clock. The MSTP groups are sparsely populated. Unimplemented
gate clocks must not be declared.
The clocks, clock-output-names and clock-indices properties contain one entry
per gate clock. The MSTP groups are sparsely populated. Unimplemented gate
clocks must not be declared.
Example
......
......@@ -10,14 +10,17 @@ Required properties:
"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
"allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
"allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
"allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-a10-axi-clk" - for the AXI clock
"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
"allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
......@@ -26,24 +29,29 @@ Required properties:
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
"allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
"allwinner,sun9i-a80-ahb1-gates-clk" - for the AHB1 gates on A80
"allwinner,sun9i-a80-ahb2-gates-clk" - for the AHB2 gates on A80
"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
"allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
"allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80
"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
"allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80
"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
"allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
"allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
"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
......@@ -63,8 +71,9 @@ Required properties for all clocks:
multiplexed clocks, the list order must match the hardware
programming order.
- #clock-cells : from common clock binding; shall be set to 0 except for
"allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk" and
"allwinner,sun4i-pll6-clk" where it shall be set to 1
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"
- 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.
......@@ -79,6 +88,12 @@ Clock consumers should specify the desired clocks they use with a
"clocks" phandle cell. Consumers that are using a gated clock should
provide an additional ID in their clock property. This ID is the
offset of the bit controlling this particular gate in the register.
For the other clocks with "#clock-cells" = 1, the additional ID shall
refer to the index of the output.
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".
For example:
......@@ -106,6 +121,14 @@ pll5: clk@01c20020 {
clock-output-names = "pll5_ddr", "pll5_other";
};
pll6: clk@01c20028 {
#clock-cells = <1>;
compatible = "allwinner,sun6i-a31-pll6-clk";
reg = <0x01c20028 0x4>;
clocks = <&osc24M>;
clock-output-names = "pll6", "pll6x2";
};
cpu: cpu@01c20054 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-cpu-clk";
......
......@@ -2576,8 +2576,9 @@ F: drivers/media/platform/coda/
COMMON CLK FRAMEWORK
M: Mike Turquette <mturquette@linaro.org>
M: Stephen Boyd <sboyd@codeaurora.org>
L: linux-kernel@vger.kernel.org
T: git git://git.linaro.org/people/mturquette/linux.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
S: Maintained
F: drivers/clk/
X: drivers/clk/clkdev.c
......
......@@ -177,6 +177,9 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
dtb-$(CONFIG_MACH_MESON6) += meson6-atv1200.dtb
dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \
pxa910-dkb.dtb \
mmp2-brownstone.dtb
dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
dtb-$(CONFIG_ARCH_MXC) += \
imx1-ads.dtb \
......
......@@ -8,7 +8,7 @@
*/
/dts-v1/;
/include/ "mmp2.dtsi"
#include "mmp2.dtsi"
/ {
model = "Marvell MMP2 Brownstone Development Board";
......
......@@ -7,7 +7,8 @@
* publishhed by the Free Software Foundation.
*/
/include/ "skeleton.dtsi"
#include "skeleton.dtsi"
#include <dt-bindings/clock/marvell,mmp2.h>
/ {
aliases {
......@@ -135,6 +136,8 @@ uart1: uart@d4030000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4030000 0x1000>;
interrupts = <27>;
clocks = <&soc_clocks MMP2_CLK_UART0>;
resets = <&soc_clocks MMP2_CLK_UART0>;
status = "disabled";
};
......@@ -142,6 +145,8 @@ uart2: uart@d4017000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4017000 0x1000>;
interrupts = <28>;
clocks = <&soc_clocks MMP2_CLK_UART1>;
resets = <&soc_clocks MMP2_CLK_UART1>;
status = "disabled";
};
......@@ -149,6 +154,8 @@ uart3: uart@d4018000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4018000 0x1000>;
interrupts = <24>;
clocks = <&soc_clocks MMP2_CLK_UART2>;
resets = <&soc_clocks MMP2_CLK_UART2>;
status = "disabled";
};
......@@ -156,6 +163,8 @@ uart4: uart@d4016000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4016000 0x1000>;
interrupts = <46>;
clocks = <&soc_clocks MMP2_CLK_UART3>;
resets = <&soc_clocks MMP2_CLK_UART3>;
status = "disabled";
};
......@@ -168,6 +177,8 @@ gpio@d4019000 {
#gpio-cells = <2>;
interrupts = <49>;
interrupt-names = "gpio_mux";
clocks = <&soc_clocks MMP2_CLK_GPIO>;
resets = <&soc_clocks MMP2_CLK_GPIO>;
interrupt-controller;
#interrupt-cells = <1>;
ranges;
......@@ -201,6 +212,8 @@ twsi1: i2c@d4011000 {
compatible = "mrvl,mmp-twsi";
reg = <0xd4011000 0x1000>;
interrupts = <7>;
clocks = <&soc_clocks MMP2_CLK_TWSI0>;
resets = <&soc_clocks MMP2_CLK_TWSI0>;
#address-cells = <1>;
#size-cells = <0>;
mrvl,i2c-fast-mode;
......@@ -211,6 +224,8 @@ twsi2: i2c@d4025000 {
compatible = "mrvl,mmp-twsi";
reg = <0xd4025000 0x1000>;
interrupts = <58>;
clocks = <&soc_clocks MMP2_CLK_TWSI1>;
resets = <&soc_clocks MMP2_CLK_TWSI1>;
status = "disabled";
};
......@@ -220,8 +235,20 @@ rtc: rtc@d4010000 {
interrupts = <1 0>;
interrupt-names = "rtc 1Hz", "rtc alarm";
interrupt-parent = <&intcmux5>;
clocks = <&soc_clocks MMP2_CLK_RTC>;
resets = <&soc_clocks MMP2_CLK_RTC>;
status = "disabled";
};
};
soc_clocks: clocks{
compatible = "marvell,mmp2-clock";
reg = <0xd4050000 0x1000>,
<0xd4282800 0x400>,
<0xd4015000 0x1000>;
reg-names = "mpmu", "apmu", "apbc";
#clock-cells = <1>;
#reset-cells = <1>;
};
};
};
......@@ -8,7 +8,7 @@
*/
/dts-v1/;
/include/ "pxa168.dtsi"
#include "pxa168.dtsi"
/ {
model = "Marvell PXA168 Aspenite Development Board";
......
......@@ -7,7 +7,8 @@
* publishhed by the Free Software Foundation.
*/
/include/ "skeleton.dtsi"
#include "skeleton.dtsi"
#include <dt-bindings/clock/marvell,pxa168.h>
/ {
aliases {
......@@ -59,6 +60,8 @@ uart1: uart@d4017000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4017000 0x1000>;
interrupts = <27>;
clocks = <&soc_clocks PXA168_CLK_UART0>;
resets = <&soc_clocks PXA168_CLK_UART0>;
status = "disabled";
};
......@@ -66,6 +69,8 @@ uart2: uart@d4018000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4018000 0x1000>;
interrupts = <28>;
clocks = <&soc_clocks PXA168_CLK_UART1>;
resets = <&soc_clocks PXA168_CLK_UART1>;
status = "disabled";
};
......@@ -73,6 +78,8 @@ uart3: uart@d4026000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4026000 0x1000>;
interrupts = <29>;
clocks = <&soc_clocks PXA168_CLK_UART2>;
resets = <&soc_clocks PXA168_CLK_UART2>;
status = "disabled";
};
......@@ -84,6 +91,8 @@ gpio@d4019000 {
gpio-controller;
#gpio-cells = <2>;
interrupts = <49>;
clocks = <&soc_clocks PXA168_CLK_GPIO>;
resets = <&soc_clocks PXA168_CLK_GPIO>;
interrupt-names = "gpio_mux";
interrupt-controller;
#interrupt-cells = <1>;
......@@ -110,6 +119,8 @@ twsi1: i2c@d4011000 {
compatible = "mrvl,mmp-twsi";
reg = <0xd4011000 0x1000>;
interrupts = <7>;
clocks = <&soc_clocks PXA168_CLK_TWSI0>;
resets = <&soc_clocks PXA168_CLK_TWSI0>;
mrvl,i2c-fast-mode;
status = "disabled";
};
......@@ -118,6 +129,8 @@ twsi2: i2c@d4025000 {
compatible = "mrvl,mmp-twsi";
reg = <0xd4025000 0x1000>;
interrupts = <58>;
clocks = <&soc_clocks PXA168_CLK_TWSI1>;
resets = <&soc_clocks PXA168_CLK_TWSI1>;
status = "disabled";
};
......@@ -126,8 +139,20 @@ rtc: rtc@d4010000 {
reg = <0xd4010000 0x1000>;
interrupts = <5 6>;
interrupt-names = "rtc 1Hz", "rtc alarm";
clocks = <&soc_clocks PXA168_CLK_RTC>;
resets = <&soc_clocks PXA168_CLK_RTC>;
status = "disabled";
};
};
soc_clocks: clocks{
compatible = "marvell,pxa168-clock";
reg = <0xd4050000 0x1000>,
<0xd4282800 0x400>,
<0xd4015000 0x1000>;
reg-names = "mpmu", "apmu", "apbc";
#clock-cells = <1>;
#reset-cells = <1>;
};
};
};
......@@ -8,7 +8,7 @@
*/
/dts-v1/;
/include/ "pxa910.dtsi"
#include "pxa910.dtsi"
/ {
model = "Marvell PXA910 DKB Development Board";
......
......@@ -7,7 +7,8 @@
* publishhed by the Free Software Foundation.
*/
/include/ "skeleton.dtsi"
#include "skeleton.dtsi"
#include <dt-bindings/clock/marvell,pxa910.h>
/ {
aliases {
......@@ -71,6 +72,8 @@ uart1: uart@d4017000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4017000 0x1000>;
interrupts = <27>;
clocks = <&soc_clocks PXA910_CLK_UART0>;
resets = <&soc_clocks PXA910_CLK_UART0>;
status = "disabled";
};
......@@ -78,6 +81,8 @@ uart2: uart@d4018000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4018000 0x1000>;
interrupts = <28>;
clocks = <&soc_clocks PXA910_CLK_UART1>;
resets = <&soc_clocks PXA910_CLK_UART1>;
status = "disabled";
};
......@@ -85,6 +90,8 @@ uart3: uart@d4036000 {
compatible = "mrvl,mmp-uart";
reg = <0xd4036000 0x1000>;
interrupts = <59>;
clocks = <&soc_clocks PXA910_CLK_UART2>;
resets = <&soc_clocks PXA910_CLK_UART2>;
status = "disabled";
};
......@@ -97,6 +104,8 @@ gpio@d4019000 {
#gpio-cells = <2>;
interrupts = <49>;
interrupt-names = "gpio_mux";
clocks = <&soc_clocks PXA910_CLK_GPIO>;
resets = <&soc_clocks PXA910_CLK_GPIO>;
interrupt-controller;
#interrupt-cells = <1>;
ranges;
......@@ -124,6 +133,8 @@ twsi1: i2c@d4011000 {
#size-cells = <0>;
reg = <0xd4011000 0x1000>;
interrupts = <7>;
clocks = <&soc_clocks PXA910_CLK_TWSI0>;
resets = <&soc_clocks PXA910_CLK_TWSI0>;
mrvl,i2c-fast-mode;
status = "disabled";
};
......@@ -134,6 +145,8 @@ twsi2: i2c@d4037000 {
#size-cells = <0>;
reg = <0xd4037000 0x1000>;
interrupts = <54>;
clocks = <&soc_clocks PXA910_CLK_TWSI1>;
resets = <&soc_clocks PXA910_CLK_TWSI1>;
status = "disabled";
};
......@@ -142,8 +155,21 @@ rtc: rtc@d4010000 {
reg = <0xd4010000 0x1000>;
interrupts = <5 6>;
interrupt-names = "rtc 1Hz", "rtc alarm";
clocks = <&soc_clocks PXA910_CLK_RTC>;
resets = <&soc_clocks PXA910_CLK_RTC>;
status = "disabled";
};
};
soc_clocks: clocks{
compatible = "marvell,pxa910-clock";
reg = <0xd4050000 0x1000>,
<0xd4282800 0x400>,
<0xd4015000 0x1000>,
<0xd403b000 0x1000>;
reg-names = "mpmu", "apmu", "apbc", "apbcp";
#clock-cells = <1>;
#reset-cells = <1>;
};
};
};
......@@ -188,19 +188,11 @@ apb0_gates: clk@01c20068 {
"apb0_ir1", "apb0_keypad";
};
apb1_mux: apb1_mux@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
apb1: clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1";
};
......
......@@ -176,19 +176,11 @@ apb0_gates: clk@01c20068 {
"apb0_ir", "apb0_keypad";
};
apb1_mux: apb1_mux@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
apb1: clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1";
};
......
......@@ -161,19 +161,11 @@ apb0_gates: clk@01c20068 {
clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir";
};
apb1_mux: apb1_mux@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
apb1: clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1";
};
......
......@@ -229,19 +229,11 @@ apb1_gates: clk@01c20068 {
"apb1_daudio1";
};
apb2_mux: apb2_mux@01c20058 {
apb2: clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-mux-clk";
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
clock-output-names = "apb2_mux";
};
apb2: apb2@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun6i-a31-apb2-div-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb2_mux>;
clock-output-names = "apb2";
};
......
......@@ -236,19 +236,11 @@ apb0_gates: clk@01c20068 {
"apb0_iis2", "apb0_keypad";
};
apb1_mux: apb1_mux@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-mux-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1_mux";
};
apb1: apb1@01c20058 {
apb1: clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb1_mux>;
clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
clock-output-names = "apb1";
};
......
......@@ -189,19 +189,11 @@ apb1_gates: clk@01c20068 {
"apb1_daudio0", "apb1_daudio1";
};
apb2_mux: apb2_mux_clk@01c20058 {
apb2: clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-apb1-mux-clk";
compatible = "allwinner,sun4i-a10-apb1-clk";
reg = <0x01c20058 0x4>;
clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
clock-output-names = "apb2_mux";
};
apb2: apb2_clk@01c20058 {
#clock-cells = <0>;
compatible = "allwinner,sun6i-a31-apb2-div-clk";
reg = <0x01c20058 0x4>;
clocks = <&apb2_mux>;
clock-output-names = "apb2";
};
......
......@@ -86,11 +86,12 @@ config MACH_GPLUGD
config MACH_MMP_DT
bool "Support MMP (ARMv5) platforms from device tree"
select CPU_PXA168
select CPU_PXA910
select USE_OF
select PINCTRL
select PINCTRL_SINGLE
select COMMON_CLK
select ARCH_HAS_RESET_CONTROLLER
select CPU_MOHAWK
help
Include support for Marvell MMP2 based platforms using
the device tree. Needn't select any other machine while
......@@ -99,10 +100,12 @@ config MACH_MMP_DT
config MACH_MMP2_DT
bool "Support MMP2 (ARMv7) platforms from device tree"
depends on !CPU_MOHAWK
select CPU_MMP2
select USE_OF
select PINCTRL
select PINCTRL_SINGLE
select COMMON_CLK
select ARCH_HAS_RESET_CONTROLLER
select CPU_PJ4
help
Include support for Marvell MMP2 based platforms using
the device tree.
......@@ -111,21 +114,18 @@ endmenu
config CPU_PXA168
bool
select COMMON_CLK
select CPU_MOHAWK
help
Select code specific to PXA168
config CPU_PXA910
bool
select COMMON_CLK
select CPU_MOHAWK
help
Select code specific to PXA910
config CPU_MMP2
bool
select COMMON_CLK
select CPU_PJ4
help
Select code specific to MMP2. MMP2 is ARMv7 compatible.
......
......@@ -11,63 +11,42 @@
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/hardware/cache-tauros2.h>
#include "common.h"
extern void __init mmp_dt_init_timer(void);
static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4026000, "pxa2xx-uart.2", NULL),
OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4025000, "pxa2xx-i2c.1", NULL),
OF_DEV_AUXDATA("marvell,mmp-gpio", 0xd4019000, "mmp-gpio", NULL),
OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
{}
static const char *pxa168_dt_board_compat[] __initdata = {
"mrvl,pxa168-aspenite",
NULL,
};
static const struct of_dev_auxdata pxa910_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4036000, "pxa2xx-uart.2", NULL),
OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4037000, "pxa2xx-i2c.1", NULL),
OF_DEV_AUXDATA("marvell,mmp-gpio", 0xd4019000, "mmp-gpio", NULL),
OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
{}
static const char *pxa910_dt_board_compat[] __initdata = {
"mrvl,pxa910-dkb",
NULL,
};
static void __init pxa168_dt_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
pxa168_auxdata_lookup, NULL);
}
static void __init pxa910_dt_init(void)
static void __init mmp_init_time(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
pxa910_auxdata_lookup, NULL);
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init(0);
#endif
mmp_dt_init_timer();
of_clk_init(NULL);
}
static const char *mmp_dt_board_compat[] __initdata = {
"mrvl,pxa168-aspenite",
"mrvl,pxa910-dkb",
NULL,
};
DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
.map_io = mmp_map_io,
.init_time = mmp_dt_init_timer,
.init_machine = pxa168_dt_init,
.dt_compat = mmp_dt_board_compat,
.init_time = mmp_init_time,
.dt_compat = pxa168_dt_board_compat,
MACHINE_END
DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)")
.map_io = mmp_map_io,
.init_time = mmp_dt_init_timer,
.init_machine = pxa910_dt_init,
.dt_compat = mmp_dt_board_compat,
.init_time = mmp_init_time,
.dt_compat = pxa910_dt_board_compat,
MACHINE_END
......@@ -12,29 +12,22 @@
#include <linux/io.h>
#include <linux/irqchip.h>
#include <linux/of_platform.h>
#include <linux/clk-provider.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/hardware/cache-tauros2.h>
#include "common.h"
extern void __init mmp_dt_init_timer(void);
static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.2", NULL),
OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4016000, "pxa2xx-uart.3", NULL),
OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4011000, "pxa2xx-i2c.0", NULL),
OF_DEV_AUXDATA("mrvl,mmp-twsi", 0xd4025000, "pxa2xx-i2c.1", NULL),
OF_DEV_AUXDATA("marvell,mmp-gpio", 0xd4019000, "mmp2-gpio", NULL),
OF_DEV_AUXDATA("mrvl,mmp-rtc", 0xd4010000, "sa1100-rtc", NULL),
{}
};
static void __init mmp2_dt_init(void)
static void __init mmp_init_time(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
mmp2_auxdata_lookup, NULL);
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init(0);
#endif
mmp_dt_init_timer();
of_clk_init(NULL);
}
static const char *mmp2_dt_board_compat[] __initdata = {
......@@ -44,7 +37,6 @@ static const char *mmp2_dt_board_compat[] __initdata = {
DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
.map_io = mmp_map_io,
.init_time = mmp_dt_init_timer,
.init_machine = mmp2_dt_init,
.init_time = mmp_init_time,
.dt_compat = mmp2_dt_board_compat,
MACHINE_END
......@@ -111,6 +111,7 @@ static struct clk dpll3_ck;
static const char *dpll3_ck_parent_names[] = {
"sys_ck",
"sys_ck",
};
static const struct clk_ops dpll3_ck_ops = {
......@@ -733,6 +734,10 @@ static const char *corex2_fck_parent_names[] = {
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 = {
......@@ -744,7 +749,7 @@ static struct clk_hw_omap cpefuse_fck_hw = {
.clkdm_name = "core_l4_clkdm",
};
DEFINE_STRUCT_CLK(cpefuse_fck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(cpefuse_fck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk csi2_96m_fck;
......@@ -775,7 +780,7 @@ static struct clk_hw_omap d2d_26m_fck_hw = {
.clkdm_name = "d2d_clkdm",
};
DEFINE_STRUCT_CLK(d2d_26m_fck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(d2d_26m_fck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk des1_ick;
......@@ -1046,7 +1051,7 @@ static struct clk_hw_omap dss2_alwon_fck_hw = {
.clkdm_name = "dss_clkdm",
};
DEFINE_STRUCT_CLK(dss2_alwon_fck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(dss2_alwon_fck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk dss_96m_fck;
......@@ -1368,7 +1373,7 @@ 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, dpll3_ck_parent_names, core_l4_ick_ops);
DEFINE_STRUCT_CLK(wkup_l4_ick, cpefuse_fck_parent_names, core_l4_ick_ops);
static struct clk gpio1_ick;
......@@ -1862,7 +1867,7 @@ static struct clk_hw_omap hecc_ck_hw = {
.clkdm_name = "core_l3_clkdm",
};
DEFINE_STRUCT_CLK(hecc_ck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(hecc_ck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk hsotgusb_fck_am35xx;
......@@ -1875,7 +1880,7 @@ static struct clk_hw_omap hsotgusb_fck_am35xx_hw = {
.clkdm_name = "core_l3_clkdm",
};
DEFINE_STRUCT_CLK(hsotgusb_fck_am35xx, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(hsotgusb_fck_am35xx, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk hsotgusb_ick_3430es1;
......@@ -2411,7 +2416,7 @@ static struct clk_hw_omap modem_fck_hw = {
.clkdm_name = "d2d_clkdm",
};
DEFINE_STRUCT_CLK(modem_fck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(modem_fck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk mspro_fck;
......@@ -2710,7 +2715,7 @@ static struct clk_hw_omap sr1_fck_hw = {
.clkdm_name = "wkup_clkdm",
};
DEFINE_STRUCT_CLK(sr1_fck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(sr1_fck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk sr2_fck;
......@@ -2724,7 +2729,7 @@ static struct clk_hw_omap sr2_fck_hw = {
.clkdm_name = "wkup_clkdm",
};
DEFINE_STRUCT_CLK(sr2_fck, dpll3_ck_parent_names, aes2_ick_ops);
DEFINE_STRUCT_CLK(sr2_fck, cpefuse_fck_parent_names, aes2_ick_ops);
static struct clk sr_l4_ick;
......
......@@ -474,7 +474,7 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
*/
long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk)
struct clk_hw **best_parent_clk)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct dpll_data *dd;
......@@ -488,10 +488,10 @@ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
if (__clk_get_rate(dd->clk_bypass) == rate &&
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
*best_parent_clk = dd->clk_bypass;
*best_parent_clk = __clk_get_hw(dd->clk_bypass);
} else {
rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
*best_parent_clk = dd->clk_ref;
*best_parent_clk = __clk_get_hw(dd->clk_ref);
}
*best_parent_rate = rate;
......
......@@ -223,7 +223,7 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
*/
long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk)
struct clk_hw **best_parent_clk)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct dpll_data *dd;
......@@ -237,11 +237,11 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
if (__clk_get_rate(dd->clk_bypass) == rate &&
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
*best_parent_clk = dd->clk_bypass;
*best_parent_clk = __clk_get_hw(dd->clk_bypass);
} else {
rate = omap4_dpll_regm4xen_round_rate(hw, rate,
best_parent_rate);
*best_parent_clk = dd->clk_ref;
*best_parent_clk = __clk_get_hw(dd->clk_ref);
}
*best_parent_rate = rate;
......
......@@ -374,7 +374,7 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk,
struct clk_hw **best_parent_clk,
int scale, int maxdiv)
{
struct clk *pc, *bpc, *free;
......@@ -453,7 +453,7 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
}
*best_parent_rate = bpr;
*best_parent_clk = bpc;
*best_parent_clk = __clk_get_hw(bpc);
return br;
}
......@@ -547,7 +547,7 @@ 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 *best_parent_rate,
struct clk **best_parent_clk)
struct clk_hw **best_parent_clk)
{
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
best_parent_clk, 2, 512);
......@@ -679,7 +679,7 @@ 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 *best_parent_rate,
struct clk **best_parent_clk)
struct clk_hw **best_parent_clk)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale, maxdiv;
......@@ -898,7 +898,7 @@ 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 *best_parent_rate,
struct clk **best_parent_clk)
struct clk_hw **best_parent_clk)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
......
......@@ -57,7 +57,7 @@ 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 *best_parent_rate,
struct clk **best_parent_clk)
struct clk_hw **best_parent_hw)
{
struct clk *parent = NULL;
long best_rate = -EINVAL;
......@@ -84,7 +84,7 @@ static long clk_programmable_determine_rate(struct clk_hw *hw,
if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate;
*best_parent_rate = parent_rate;
*best_parent_clk = parent;
*best_parent_hw = __clk_get_hw(parent);
}
if (!best_rate)
......
......@@ -1032,7 +1032,7 @@ 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 *best_parent_rate, struct clk **best_parent)
unsigned long *best_parent_rate, struct clk_hw **best_parent)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct clk *clk = hw->clk;
......@@ -1075,7 +1075,7 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
if (delta < best_delta) {
best_delta = delta;
best_rate = other_rate;
*best_parent = parent;
*best_parent = __clk_get_hw(parent);
*best_parent_rate = parent_rate;
}
}
......
......@@ -57,7 +57,7 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p)
struct clk_hw **best_parent_p)
{
struct clk_composite *composite = to_clk_composite(hw);
const struct clk_ops *rate_ops = composite->rate_ops;
......@@ -80,8 +80,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
*best_parent_p = NULL;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
*best_parent_p = clk_get_parent(mux_hw->clk);
*best_parent_rate = __clk_get_rate(*best_parent_p);
parent = clk_get_parent(mux_hw->clk);
*best_parent_p = __clk_get_hw(parent);
*best_parent_rate = __clk_get_rate(parent);
return rate_ops->round_rate(rate_hw, rate,
best_parent_rate);
......@@ -103,7 +104,7 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
if (!rate_diff || !*best_parent_p
|| best_rate_diff > rate_diff) {
*best_parent_p = parent;
*best_parent_p = __clk_get_hw(parent);
*best_parent_rate = parent_rate;
best_rate_diff = rate_diff;
best_rate = tmp_rate;
......
......@@ -77,7 +77,7 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
else {
if (mux->flags & CLK_MUX_INDEX_BIT)
index = (1 << ffs(index));
index = 1 << index;
if (mux->flags & CLK_MUX_INDEX_ONE)
index++;
......
......@@ -218,7 +218,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "Invalid device type\n");
return -EINVAL;
};
}
/* Store clocks of_node in first element of s2mps11_clks array */
s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init);
......
......@@ -240,7 +240,6 @@ static const struct file_operations clk_dump_fops = {
.release = single_release,
};
/* caller must hold prepare_lock */
static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
{
struct dentry *d;
......@@ -354,13 +353,13 @@ static void clk_debug_unregister(struct clk *clk)
mutex_unlock(&clk_debug_lock);
}
struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
void *data, const struct file_operations *fops)
{
struct dentry *d = NULL;
if (clk->dentry)
d = debugfs_create_file(name, mode, clk->dentry, data, fops);
if (hw->clk->dentry)
d = debugfs_create_file(name, mode, hw->clk->dentry, data, fops);
return d;
}
......@@ -574,11 +573,6 @@ unsigned int __clk_get_enable_count(struct clk *clk)
return !clk ? 0 : clk->enable_count;
}
unsigned int __clk_get_prepare_count(struct clk *clk)
{
return !clk ? 0 : clk->prepare_count;
}
unsigned long __clk_get_rate(struct clk *clk)
{
unsigned long ret;
......@@ -601,7 +595,7 @@ unsigned long __clk_get_rate(struct clk *clk)
}
EXPORT_SYMBOL_GPL(__clk_get_rate);
unsigned long __clk_get_accuracy(struct clk *clk)
static unsigned long __clk_get_accuracy(struct clk *clk)
{
if (!clk)
return 0;
......@@ -707,7 +701,7 @@ struct clk *__clk_lookup(const char *name)
*/
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p)
struct clk_hw **best_parent_p)
{
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
......@@ -743,7 +737,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
out:
if (best_parent)
*best_parent_p = best_parent;
*best_parent_p = best_parent->hw;
*best_parent_rate = best;
return best;
......@@ -951,6 +945,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = 0;
struct clk *parent;
struct clk_hw *parent_hw;
if (!clk)
return 0;
......@@ -959,10 +954,11 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
if (parent)
parent_rate = parent->rate;
if (clk->ops->determine_rate)
if (clk->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
&parent);
else if (clk->ops->round_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);
......@@ -1350,6 +1346,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
{
struct clk *top = clk;
struct clk *old_parent, *parent;
struct clk_hw *parent_hw;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
int p_index = 0;
......@@ -1365,9 +1362,11 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long 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,
&best_parent_rate,
&parent);
&parent_hw);
parent = parent_hw->clk;
} else if (clk->ops->round_rate) {
new_rate = clk->ops->round_rate(clk->hw, rate,
&best_parent_rate);
......@@ -1614,7 +1613,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
if (clk->num_parents == 1) {
if (IS_ERR_OR_NULL(clk->parent))
ret = clk->parent = __clk_lookup(clk->parent_names[0]);
clk->parent = __clk_lookup(clk->parent_names[0]);
ret = clk->parent;
goto out;
}
......@@ -1944,7 +1943,6 @@ int __clk_init(struct device *dev, struct clk *clk)
else
clk->rate = 0;
clk_debug_register(clk);
/*
* walk the list of orphan clocks and reparent any that are children of
* this clock
......@@ -1979,6 +1977,9 @@ int __clk_init(struct device *dev, struct clk *clk)
out:
clk_prepare_unlock();
if (!ret)
clk_debug_register(clk);
return ret;
}
......@@ -2273,14 +2274,17 @@ int __clk_get(struct clk *clk)
void __clk_put(struct clk *clk)
{
struct module *owner;
if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
return;
clk_prepare_lock();
owner = clk->owner;
kref_put(&clk->ref, __clk_release);
clk_prepare_unlock();
module_put(clk->owner);
module_put(owner);
}
/*** clk rate change notifiers ***/
......
......@@ -38,44 +38,44 @@
#include "clk.h"
/* clock parent list */
static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", };
static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", };
static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", };
static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", };
static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", };
static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", };
static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", };
static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", };
static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", };
static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", };
static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", };
static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
static const char *timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
static const char *timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
static const char *timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
static const char *timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
static const char *timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
static const char *timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
static const char *timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
static const char *timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
static const char *timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
static const char *timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
static const char *uart0_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *uart1_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *uart2_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *uart3_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *uart4_mux_p[] __initconst = { "osc26m", "pclk", };
static const char *spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
static const char *spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
static const char *spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
/* share axi parent */
static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", };
static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", };
static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", };
static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", };
static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4",
static const char *saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
static const char *pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
static const char *pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
static const char *sd_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
static const char *g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *venc_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
"armpll3", "armpll5", };
static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4",
static const char *edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
"armpll3", "armpll5", };
static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", };
static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", };
static const char *rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
static const char *mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
static const char *mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
/* fixed rate clocks */
......@@ -296,7 +296,7 @@ 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 *best_parent_rate,
struct clk **best_parent_p)
struct clk_hw **best_parent_p)
{
struct clk_mmc *mclk = to_mmc(hw);
unsigned long best = 0;
......
......@@ -2,7 +2,12 @@
# Makefile for mmp specific clk
#
obj-y += clk-apbc.o clk-apmu.o clk-frac.o
obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
......
......@@ -22,19 +22,12 @@
* numerator/denominator = Fin / (Fout * factor)
*/
#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
struct clk_factor {
struct clk_hw hw;
void __iomem *base;
struct clk_factor_masks *masks;
struct clk_factor_tbl *ftbl;
unsigned int ftbl_cnt;
};
#define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
{
struct clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor *factor = to_clk_factor(hw);
unsigned long rate = 0, prev_rate;
int i;
......@@ -58,8 +51,8 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_factor *factor = to_clk_factor(hw);
struct clk_factor_masks *masks = factor->masks;
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
unsigned int val, num, den;
val = readl_relaxed(factor->base);
......@@ -81,11 +74,12 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct clk_factor *factor = to_clk_factor(hw);
struct clk_factor_masks *masks = factor->masks;
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
unsigned long flags = 0;
for (i = 0; i < factor->ftbl_cnt; i++) {
prev_rate = rate;
......@@ -97,6 +91,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
if (i > 0)
i--;
if (factor->lock)
spin_lock_irqsave(factor->lock, flags);
val = readl_relaxed(factor->base);
val &= ~(masks->num_mask << masks->num_shift);
......@@ -107,21 +104,65 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
writel_relaxed(val, factor->base);
if (factor->lock)
spin_unlock_irqrestore(factor->lock, flags);
return 0;
}
static void clk_factor_init(struct clk_hw *hw)
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
u32 val, num, den;
int i;
unsigned long flags = 0;
if (factor->lock)
spin_lock_irqsave(factor->lock, flags);
val = readl(factor->base);
/* calculate numerator */
num = (val >> masks->num_shift) & masks->num_mask;
/* calculate denominator */
den = (val >> masks->den_shift) & masks->den_mask;
for (i = 0; i < factor->ftbl_cnt; i++)
if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
break;
if (i >= factor->ftbl_cnt) {
val &= ~(masks->num_mask << masks->num_shift);
val |= (factor->ftbl[0].num & masks->num_mask) <<
masks->num_shift;
val &= ~(masks->den_mask << masks->den_shift);
val |= (factor->ftbl[0].den & masks->den_mask) <<
masks->den_shift;
writel(val, factor->base);
}
if (factor->lock)
spin_unlock_irqrestore(factor->lock, flags);
}
static struct clk_ops clk_factor_ops = {
.recalc_rate = clk_factor_recalc_rate,
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
.init = clk_factor_init,
};
struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
unsigned long flags, void __iomem *base,
struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
unsigned int ftbl_cnt)
struct mmp_clk_factor_masks *masks,
struct mmp_clk_factor_tbl *ftbl,
unsigned int ftbl_cnt, spinlock_t *lock)
{
struct clk_factor *factor;
struct mmp_clk_factor *factor;
struct clk_init_data init;
struct clk *clk;
......@@ -142,6 +183,7 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
factor->ftbl = ftbl;
factor->ftbl_cnt = ftbl_cnt;
factor->hw.init = &init;
factor->lock = lock;
init.name = name;
init.ops = &clk_factor_ops;
......
/*
* mmp gate clock operation source file
*
* Copyright (C) 2014 Marvell
* Chao Xie <chao.xie@marvell.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/delay.h>
#include "clk.h"
/*
* Some clocks will have mutiple bits to enable the clocks, and
* the bits to disable the clock is not same as enabling bits.
*/
#define to_clk_mmp_gate(hw) container_of(hw, struct mmp_clk_gate, hw)
static int mmp_clk_gate_enable(struct clk_hw *hw)
{
struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
struct clk *clk = hw->clk;
unsigned long flags = 0;
unsigned long rate;
u32 tmp;
if (gate->lock)
spin_lock_irqsave(gate->lock, flags);
tmp = readl(gate->reg);
tmp &= ~gate->mask;
tmp |= gate->val_enable;
writel(tmp, gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
rate = __clk_get_rate(clk);
/* Need delay 2 cycles. */
udelay(2000000/rate);
}
return 0;
}
static void mmp_clk_gate_disable(struct clk_hw *hw)
{
struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
unsigned long flags = 0;
u32 tmp;
if (gate->lock)
spin_lock_irqsave(gate->lock, flags);
tmp = readl(gate->reg);
tmp &= ~gate->mask;
tmp |= gate->val_disable;
writel(tmp, gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
}
static int mmp_clk_gate_is_enabled(struct clk_hw *hw)
{
struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
unsigned long flags = 0;
u32 tmp;
if (gate->lock)
spin_lock_irqsave(gate->lock, flags);
tmp = readl(gate->reg);
if (gate->lock)
spin_unlock_irqrestore(gate->lock, flags);
return (tmp & gate->mask) == gate->val_enable;
}
const struct clk_ops mmp_clk_gate_ops = {
.enable = mmp_clk_gate_enable,
.disable = mmp_clk_gate_disable,
.is_enabled = mmp_clk_gate_is_enabled,
};
struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,
unsigned int gate_flags, spinlock_t *lock)
{
struct mmp_clk_gate *gate;
struct clk *clk;
struct clk_init_data init;
/* allocate the gate */
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate) {
pr_err("%s:%s could not allocate gate clk\n", __func__, name);
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &mmp_clk_gate_ops;
init.flags = flags | CLK_IS_BASIC;
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
/* struct clk_gate assignments */
gate->reg = reg;
gate->mask = mask;
gate->val_enable = val_enable;
gate->val_disable = val_disable;
gate->flags = gate_flags;
gate->lock = lock;
gate->hw.init = &init;
clk = clk_register(dev, &gate->hw);
if (IS_ERR(clk))
kfree(gate);
return clk;
}
This diff is collapsed.
......@@ -54,7 +54,7 @@
static DEFINE_SPINLOCK(clk_lock);
static struct clk_factor_masks uart_factor_masks = {
static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
......@@ -62,7 +62,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
static struct clk_factor_tbl uart_factor_tbl[] = {
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 14634, .den = 2165}, /*14.745MHZ */
{.num = 3521, .den = 689}, /*19.23MHZ */
{.num = 9679, .den = 5728}, /*58.9824MHZ */
......@@ -191,7 +191,7 @@ void __init mmp2_clk_init(void)
clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
ARRAY_SIZE(uart_factor_tbl));
ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(clk, 14745600);
clk_register_clkdev(clk, "uart_pll", NULL);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -47,7 +47,7 @@
static DEFINE_SPINLOCK(clk_lock);
static struct clk_factor_masks uart_factor_masks = {
static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
......@@ -55,7 +55,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
static struct clk_factor_tbl uart_factor_tbl[] = {
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 8125, .den = 1536}, /*14.745MHZ */
};
......@@ -158,7 +158,7 @@ void __init pxa168_clk_init(void)
uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
ARRAY_SIZE(uart_factor_tbl));
ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
......
......@@ -45,7 +45,7 @@
static DEFINE_SPINLOCK(clk_lock);
static struct clk_factor_masks uart_factor_masks = {
static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
......@@ -53,7 +53,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
};
static struct clk_factor_tbl uart_factor_tbl[] = {
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 8125, .den = 1536}, /*14.745MHZ */
};
......@@ -163,7 +163,7 @@ void __init pxa910_clk_init(void)
uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
ARRAY_SIZE(uart_factor_tbl));
ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
......
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include "clk.h"
void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
int nr_clks)
{
static struct clk **clk_table;
clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
if (!clk_table)
return;
unit->clk_table = clk_table;
unit->nr_clks = nr_clks;
unit->clk_data.clks = clk_table;
unit->clk_data.clk_num = nr_clks;
of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
}
void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
struct mmp_param_fixed_rate_clk *clks,
int size)
{
int i;
struct clk *clk;
for (i = 0; i < size; i++) {
clk = clk_register_fixed_rate(NULL, clks[i].name,
clks[i].parent_name,
clks[i].flags,
clks[i].fixed_rate);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].id)
unit->clk_table[clks[i].id] = clk;
}
}
void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
struct mmp_param_fixed_factor_clk *clks,
int size)
{
struct clk *clk;
int i;
for (i = 0; i < size; i++) {
clk = clk_register_fixed_factor(NULL, clks[i].name,
clks[i].parent_name,
clks[i].flags, clks[i].mult,
clks[i].div);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].id)
unit->clk_table[clks[i].id] = clk;
}
}
void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
struct mmp_param_general_gate_clk *clks,
void __iomem *base, int size)
{
struct clk *clk;
int i;
for (i = 0; i < size; i++) {
clk = clk_register_gate(NULL, clks[i].name,
clks[i].parent_name,
clks[i].flags,
base + clks[i].offset,
clks[i].bit_idx,
clks[i].gate_flags,
clks[i].lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].id)
unit->clk_table[clks[i].id] = clk;
}
}
void mmp_register_gate_clks(struct mmp_clk_unit *unit,
struct mmp_param_gate_clk *clks,
void __iomem *base, int size)
{
struct clk *clk;
int i;
for (i = 0; i < size; i++) {
clk = mmp_clk_register_gate(NULL, clks[i].name,
clks[i].parent_name,
clks[i].flags,
base + clks[i].offset,
clks[i].mask,
clks[i].val_enable,
clks[i].val_disable,
clks[i].gate_flags,
clks[i].lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].id)
unit->clk_table[clks[i].id] = clk;
}
}
void mmp_register_mux_clks(struct mmp_clk_unit *unit,
struct mmp_param_mux_clk *clks,
void __iomem *base, int size)
{
struct clk *clk;
int i;
for (i = 0; i < size; i++) {
clk = clk_register_mux(NULL, clks[i].name,
clks[i].parent_name,
clks[i].num_parents,
clks[i].flags,
base + clks[i].offset,
clks[i].shift,
clks[i].width,
clks[i].mux_flags,
clks[i].lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].id)
unit->clk_table[clks[i].id] = clk;
}
}
void mmp_register_div_clks(struct mmp_clk_unit *unit,
struct mmp_param_div_clk *clks,
void __iomem *base, int size)
{
struct clk *clk;
int i;
for (i = 0; i < size; i++) {
clk = clk_register_divider(NULL, clks[i].name,
clks[i].parent_name,
clks[i].flags,
base + clks[i].offset,
clks[i].shift,
clks[i].width,
clks[i].div_flags,
clks[i].lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
continue;
}
if (clks[i].id)
unit->clk_table[clks[i].id] = clk;
}
}
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
struct clk *clk)
{
if (IS_ERR_OR_NULL(clk)) {
pr_err("CLK %d has invalid pointer %p\n", id, clk);
return;
}
if (id > unit->nr_clks) {
pr_err("CLK %d is invalid\n", id);
return;
}
unit->clk_table[id] = clk;
}
......@@ -7,7 +7,9 @@
#define APBC_NO_BUS_CTRL BIT(0)
#define APBC_POWER_CTRL BIT(1)
struct clk_factor_masks {
/* Clock type "factor" */
struct mmp_clk_factor_masks {
unsigned int factor;
unsigned int num_mask;
unsigned int den_mask;
......@@ -15,11 +17,113 @@ struct clk_factor_masks {
unsigned int den_shift;
};
struct clk_factor_tbl {
struct mmp_clk_factor_tbl {
unsigned int num;
unsigned int den;
};
struct mmp_clk_factor {
struct clk_hw hw;
void __iomem *base;
struct mmp_clk_factor_masks *masks;
struct mmp_clk_factor_tbl *ftbl;
unsigned int ftbl_cnt;
spinlock_t *lock;
};
extern struct clk *mmp_clk_register_factor(const char *name,
const char *parent_name, unsigned long flags,
void __iomem *base, struct mmp_clk_factor_masks *masks,
struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
spinlock_t *lock);
/* Clock type "mix" */
#define MMP_CLK_BITS_MASK(width, shift) \
(((1 << (width)) - 1) << (shift))
#define MMP_CLK_BITS_GET_VAL(data, width, shift) \
((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift))
#define MMP_CLK_BITS_SET_VAL(val, width, shift) \
(((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift))
enum {
MMP_CLK_MIX_TYPE_V1,
MMP_CLK_MIX_TYPE_V2,
MMP_CLK_MIX_TYPE_V3,
};
/* The register layout */
struct mmp_clk_mix_reg_info {
void __iomem *reg_clk_ctrl;
void __iomem *reg_clk_sel;
u8 width_div;
u8 shift_div;
u8 width_mux;
u8 shift_mux;
u8 bit_fc;
};
/* The suggested clock table from user. */
struct mmp_clk_mix_clk_table {
unsigned long rate;
u8 parent_index;
unsigned int divisor;
unsigned int valid;
};
struct mmp_clk_mix_config {
struct mmp_clk_mix_reg_info reg_info;
struct mmp_clk_mix_clk_table *table;
unsigned int table_size;
u32 *mux_table;
struct clk_div_table *div_table;
u8 div_flags;
u8 mux_flags;
};
struct mmp_clk_mix {
struct clk_hw hw;
struct mmp_clk_mix_reg_info reg_info;
struct mmp_clk_mix_clk_table *table;
u32 *mux_table;
struct clk_div_table *div_table;
unsigned int table_size;
u8 div_flags;
u8 mux_flags;
unsigned int type;
spinlock_t *lock;
};
extern const struct clk_ops mmp_clk_mix_ops;
extern struct clk *mmp_clk_register_mix(struct device *dev,
const char *name,
const char **parent_names,
u8 num_parents,
unsigned long flags,
struct mmp_clk_mix_config *config,
spinlock_t *lock);
/* Clock type "gate". MMP private gate */
#define MMP_CLK_GATE_NEED_DELAY BIT(0)
struct mmp_clk_gate {
struct clk_hw hw;
void __iomem *reg;
u32 mask;
u32 val_enable;
u32 val_disable;
unsigned int flags;
spinlock_t *lock;
};
extern const struct clk_ops mmp_clk_gate_ops;
extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u32 mask, u32 val_enable,
u32 val_disable, unsigned int gate_flags,
spinlock_t *lock);
extern struct clk *mmp_clk_register_pll2(const char *name,
const char *parent_name, unsigned long flags);
extern struct clk *mmp_clk_register_apbc(const char *name,
......@@ -28,8 +132,108 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
extern struct clk *mmp_clk_register_apmu(const char *name,
const char *parent_name, void __iomem *base, u32 enable_mask,
spinlock_t *lock);
extern struct clk *mmp_clk_register_factor(const char *name,
const char *parent_name, unsigned long flags,
void __iomem *base, struct clk_factor_masks *masks,
struct clk_factor_tbl *ftbl, unsigned int ftbl_cnt);
struct mmp_clk_unit {
unsigned int nr_clks;
struct clk **clk_table;
struct clk_onecell_data clk_data;
};
struct mmp_param_fixed_rate_clk {
unsigned int id;
char *name;
const char *parent_name;
unsigned long flags;
unsigned long fixed_rate;
};
void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
struct mmp_param_fixed_rate_clk *clks,
int size);
struct mmp_param_fixed_factor_clk {
unsigned int id;
char *name;
const char *parent_name;
unsigned long mult;
unsigned long div;
unsigned long flags;
};
void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
struct mmp_param_fixed_factor_clk *clks,
int size);
struct mmp_param_general_gate_clk {
unsigned int id;
const char *name;
const char *parent_name;
unsigned long flags;
unsigned long offset;
u8 bit_idx;
u8 gate_flags;
spinlock_t *lock;
};
void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
struct mmp_param_general_gate_clk *clks,
void __iomem *base, int size);
struct mmp_param_gate_clk {
unsigned int id;
char *name;
const char *parent_name;
unsigned long flags;
unsigned long offset;
u32 mask;
u32 val_enable;
u32 val_disable;
unsigned int gate_flags;
spinlock_t *lock;
};
void mmp_register_gate_clks(struct mmp_clk_unit *unit,
struct mmp_param_gate_clk *clks,
void __iomem *base, int size);
struct mmp_param_mux_clk {
unsigned int id;
char *name;
const char **parent_name;
u8 num_parents;
unsigned long flags;
unsigned long offset;
u8 shift;
u8 width;
u8 mux_flags;
spinlock_t *lock;
};
void mmp_register_mux_clks(struct mmp_clk_unit *unit,
struct mmp_param_mux_clk *clks,
void __iomem *base, int size);
struct mmp_param_div_clk {
unsigned int id;
char *name;
const char *parent_name;
unsigned long flags;
unsigned long offset;
u8 shift;
u8 width;
u8 div_flags;
spinlock_t *lock;
};
void mmp_register_div_clks(struct mmp_clk_unit *unit,
struct mmp_param_div_clk *clks,
void __iomem *base, int size);
#define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc) \
{ \
.width_div = (w_d), \
.shift_div = (s_d), \
.width_mux = (w_m), \
.shift_mux = (s_m), \
.bit_fc = (fc), \
}
void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
int nr_clks);
void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
struct clk *clk);
#endif
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/reset-controller.h>
#include "reset.h"
#define rcdev_to_unit(rcdev) container_of(rcdev, struct mmp_clk_reset_unit, rcdev)
static int mmp_of_reset_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
{
struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
struct mmp_clk_reset_cell *cell;
int i;
if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
return -EINVAL;
for (i = 0; i < rcdev->nr_resets; i++) {
cell = &unit->cells[i];
if (cell->clk_id == reset_spec->args[0])
break;
}
if (i == rcdev->nr_resets)
return -EINVAL;
return i;
}
static int mmp_clk_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
struct mmp_clk_reset_cell *cell;
unsigned long flags = 0;
u32 val;
cell = &unit->cells[id];
if (cell->lock)
spin_lock_irqsave(cell->lock, flags);
val = readl(cell->reg);
val |= cell->bits;
writel(val, cell->reg);
if (cell->lock)
spin_unlock_irqrestore(cell->lock, flags);
return 0;
}
static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
struct mmp_clk_reset_cell *cell;
unsigned long flags = 0;
u32 val;
cell = &unit->cells[id];
if (cell->lock)
spin_lock_irqsave(cell->lock, flags);
val = readl(cell->reg);
val &= ~cell->bits;
writel(val, cell->reg);
if (cell->lock)
spin_unlock_irqrestore(cell->lock, flags);
return 0;
}
static struct reset_control_ops mmp_clk_reset_ops = {
.assert = mmp_clk_reset_assert,
.deassert = mmp_clk_reset_deassert,
};
void mmp_clk_reset_register(struct device_node *np,
struct mmp_clk_reset_cell *cells, int nr_resets)
{
struct mmp_clk_reset_unit *unit;
unit = kzalloc(sizeof(*unit), GFP_KERNEL);
if (!unit)
return;
unit->cells = cells;
unit->rcdev.of_reset_n_cells = 1;
unit->rcdev.nr_resets = nr_resets;
unit->rcdev.ops = &mmp_clk_reset_ops;
unit->rcdev.of_node = np;
unit->rcdev.of_xlate = mmp_of_reset_xlate;
reset_controller_register(&unit->rcdev);
}
#ifndef __MACH_MMP_CLK_RESET_H
#define __MACH_MMP_CLK_RESET_H
#include <linux/reset-controller.h>
#define MMP_RESET_INVERT 1
struct mmp_clk_reset_cell {
unsigned int clk_id;
void __iomem *reg;
u32 bits;
unsigned int flags;
spinlock_t *lock;
};
struct mmp_clk_reset_unit {
struct reset_controller_dev rcdev;
struct mmp_clk_reset_cell *cells;
};
#ifdef CONFIG_RESET_CONTROLLER
void mmp_clk_reset_register(struct device_node *np,
struct mmp_clk_reset_cell *cells, int nr_resets);
#else
static inline void mmp_clk_reset_register(struct device_node *np,
struct mmp_clk_reset_cell *cells, int nr_resets)
{
}
#endif
#endif
obj-y += clk-pxa.o
obj-$(CONFIG_PXA25x) += clk-pxa25x.o
obj-$(CONFIG_PXA27x) += clk-pxa27x.o
......@@ -26,12 +26,20 @@ static struct clk_onecell_data onecell_data = {
.clk_num = CLK_MAX,
};
#define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk_cken, hw)
struct pxa_clk {
struct clk_hw hw;
struct clk_fixed_factor lp;
struct clk_fixed_factor hp;
struct clk_gate gate;
bool (*is_in_low_power)(void);
};
#define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk, hw)
static unsigned long cken_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pxa_clk_cken *pclk = to_pxa_clk(hw);
struct pxa_clk *pclk = to_pxa_clk(hw);
struct clk_fixed_factor *fix;
if (!pclk->is_in_low_power || pclk->is_in_low_power())
......@@ -48,7 +56,7 @@ static struct clk_ops cken_rate_ops = {
static u8 cken_get_parent(struct clk_hw *hw)
{
struct pxa_clk_cken *pclk = to_pxa_clk(hw);
struct pxa_clk *pclk = to_pxa_clk(hw);
if (!pclk->is_in_low_power)
return 0;
......@@ -69,29 +77,32 @@ void __init clkdev_pxa_register(int ckid, const char *con_id,
clk_register_clkdev(clk, con_id, dev_id);
}
int __init clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks)
int __init clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks)
{
int i;
struct pxa_clk_cken *pclk;
struct pxa_clk *pxa_clk;
struct clk *clk;
for (i = 0; i < nb_clks; i++) {
pclk = clks + i;
pclk->gate.lock = &lock;
clk = clk_register_composite(NULL, pclk->name,
pclk->parent_names, 2,
&pclk->hw, &cken_mux_ops,
&pclk->hw, &cken_rate_ops,
&pclk->gate.hw, &clk_gate_ops,
pclk->flags);
clkdev_pxa_register(pclk->ckid, pclk->con_id, pclk->dev_id,
clk);
pxa_clk = kzalloc(sizeof(*pxa_clk), GFP_KERNEL);
pxa_clk->is_in_low_power = clks[i].is_in_low_power;
pxa_clk->lp = clks[i].lp;
pxa_clk->hp = clks[i].hp;
pxa_clk->gate = clks[i].gate;
pxa_clk->gate.lock = &lock;
clk = clk_register_composite(NULL, clks[i].name,
clks[i].parent_names, 2,
&pxa_clk->hw, &cken_mux_ops,
&pxa_clk->hw, &cken_rate_ops,
&pxa_clk->gate.hw, &clk_gate_ops,
clks[i].flags);
clkdev_pxa_register(clks[i].ckid, clks[i].con_id,
clks[i].dev_id, clk);
}
return 0;
}
static void __init pxa_dt_clocks_init(struct device_node *np)
void __init clk_pxa_dt_common_init(struct device_node *np)
{
of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
}
CLK_OF_DECLARE(pxa_clks, "marvell,pxa-clocks", pxa_dt_clocks_init);
......@@ -25,7 +25,7 @@
static struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
}; \
static struct clk *clk_register_ ## name(void) \
static struct clk * __init clk_register_ ## name(void) \
{ \
return clk_register_composite(NULL, clk_name, \
name ## _parents, \
......@@ -40,7 +40,7 @@
static struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
}; \
static struct clk *clk_register_ ## name(void) \
static struct clk * __init clk_register_ ## name(void) \
{ \
return clk_register_composite(NULL, clk_name, \
name ## _parents, \
......@@ -66,7 +66,7 @@
* | Clock | --- | / div_hp |
* +------------+ +-----------+
*/
struct pxa_clk_cken {
struct desc_clk_cken {
struct clk_hw hw;
int ckid;
const char *name;
......@@ -102,6 +102,7 @@ static int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
extern void clkdev_pxa_register(int ckid, const char *con_id,
const char *dev_id, struct clk *clk);
extern int clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks);
extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks);
void clk_pxa_dt_common_init(struct device_node *np);
#endif
/*
* Marvell PXA25x family clocks
*
* Copyright (C) 2014 Robert Jarzmik
*
* Heavily inspired from former arch/arm/mach-pxa/pxa25x.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 <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <mach/pxa25x.h>
#include <mach/pxa2xx-regs.h>
#include <dt-bindings/clock/pxa-clock.h>
#include "clk-pxa.h"
#define KHz 1000
#define MHz (1000 * 1000)
enum {
PXA_CORE_RUN = 0,
PXA_CORE_TURBO,
};
/*
* Various clock factors driven by the CCCR register.
*/
/* Crystal Frequency to Memory Frequency Multiplier (L) */
static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, };
/* Memory Frequency to Run Mode Frequency Multiplier (M) */
static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 };
/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */
/* Note: we store the value N * 2 here. */
static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
static const char * const get_freq_khz[] = {
"core", "run", "cpll", "memory"
};
/*
* Get the clock frequency as reflected by CCCR 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 pxa25x_get_clk_frequency_khz(int info)
{
struct clk *clk;
unsigned long clks[5];
int i;
for (i = 0; i < ARRAY_SIZE(get_freq_khz); 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("Run Mode clock: %ld.%02ldMHz\n",
clks[1] / 1000000, (clks[1] % 1000000) / 10000);
pr_info("Turbo Mode clock: %ld.%02ldMHz\n",
clks[2] / 1000000, (clks[2] % 1000000) / 10000);
pr_info("Memory clock: %ld.%02ldMHz\n",
clks[3] / 1000000, (clks[3] % 1000000) / 10000);
}
return (unsigned int)clks[0];
}
static unsigned long clk_pxa25x_memory_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long cccr = CCCR;
unsigned int m = M_clk_mult[(cccr >> 5) & 0x03];
return parent_rate / m;
}
PARENTS(clk_pxa25x_memory) = { "run" };
RATE_RO_OPS(clk_pxa25x_memory, "memory");
PARENTS(pxa25x_pbus95) = { "ppll_95_85mhz", "ppll_95_85mhz" };
PARENTS(pxa25x_pbus147) = { "ppll_147_46mhz", "ppll_147_46mhz" };
PARENTS(pxa25x_osc3) = { "osc_3_6864mhz", "osc_3_6864mhz" };
#define PXA25X_CKEN(dev_id, con_id, parents, mult, div, \
bit, is_lp, flags) \
PXA_CKEN(dev_id, con_id, bit, parents, mult, div, mult, div, \
is_lp, &CKEN, CKEN_ ## bit, flags)
#define PXA25X_PBUS95_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
PXA25X_CKEN(dev_id, con_id, pxa25x_pbus95_parents, mult_hp, \
div_hp, bit, NULL, 0)
#define PXA25X_PBUS147_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay)\
PXA25X_CKEN(dev_id, con_id, pxa25x_pbus147_parents, mult_hp, \
div_hp, bit, NULL, 0)
#define PXA25X_OSC3_CKEN(dev_id, con_id, bit, mult_hp, div_hp, delay) \
PXA25X_CKEN(dev_id, con_id, pxa25x_osc3_parents, mult_hp, \
div_hp, bit, NULL, 0)
#define PXA25X_CKEN_1RATE(dev_id, con_id, bit, parents, delay) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
&CKEN, CKEN_ ## bit, 0)
#define PXA25X_CKEN_1RATE_AO(dev_id, con_id, bit, parents, delay) \
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
&CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
static struct desc_clk_cken pxa25x_clocks[] __initdata = {
PXA25X_PBUS95_CKEN("pxa2xx-mci.0", NULL, MMC, 1, 5, 0),
PXA25X_PBUS95_CKEN("pxa2xx-i2c.0", NULL, I2C, 1, 3, 0),
PXA25X_PBUS95_CKEN("pxa2xx-ir", "FICPCLK", FICP, 1, 2, 0),
PXA25X_PBUS95_CKEN("pxa25x-udc", NULL, USB, 1, 2, 5),
PXA25X_PBUS147_CKEN("pxa2xx-uart.0", NULL, FFUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-uart.1", NULL, BTUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-uart.2", NULL, STUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-uart.3", NULL, HWUART, 1, 10, 1),
PXA25X_PBUS147_CKEN("pxa2xx-i2s", NULL, I2S, 1, 10, 0),
PXA25X_PBUS147_CKEN(NULL, "AC97CLK", AC97, 1, 12, 0),
PXA25X_OSC3_CKEN("pxa25x-ssp.0", NULL, SSP, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-nssp.1", NULL, NSSP, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-nssp.2", NULL, ASSP, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-pwm.0", NULL, PWM0, 1, 1, 0),
PXA25X_OSC3_CKEN("pxa25x-pwm.1", NULL, PWM1, 1, 1, 0),
PXA25X_CKEN_1RATE("pxa2xx-fb", NULL, LCD, clk_pxa25x_memory_parents, 0),
PXA25X_CKEN_1RATE_AO("pxa2xx-pcmcia", NULL, MEMC,
clk_pxa25x_memory_parents, 0),
};
static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
{
unsigned long clkcfg;
unsigned int t;
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
if (t)
return PXA_CORE_TURBO;
return PXA_CORE_RUN;
}
static unsigned long clk_pxa25x_core_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return parent_rate;
}
PARENTS(clk_pxa25x_core) = { "run", "cpll" };
MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core");
static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long cccr = CCCR;
unsigned int n2 = N2_clk_mult[(cccr >> 7) & 0x07];
return (parent_rate / n2) * 2;
}
PARENTS(clk_pxa25x_run) = { "cpll" };
RATE_RO_OPS(clk_pxa25x_run, "run");
static unsigned long clk_pxa25x_cpll_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long clkcfg, cccr = CCCR;
unsigned int l, m, n2, t;
asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
t = clkcfg & (1 << 0);
l = L_clk_mult[(cccr >> 0) & 0x1f];
m = M_clk_mult[(cccr >> 5) & 0x03];
n2 = N2_clk_mult[(cccr >> 7) & 0x07];
if (t)
return m * l * n2 * parent_rate / 2;
return m * l * parent_rate;
}
PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" };
RATE_RO_OPS(clk_pxa25x_cpll, "cpll");
static void __init pxa25x_register_core(void)
{
clk_register_clk_pxa25x_cpll();
clk_register_clk_pxa25x_run();
clkdev_pxa_register(CLK_CORE, "core", NULL,
clk_register_clk_pxa25x_core());
}
static void __init pxa25x_register_plls(void)
{
clk_register_fixed_rate(NULL, "osc_3_6864mhz", NULL,
CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
3686400);
clk_register_fixed_rate(NULL, "osc_32_768khz", NULL,
CLK_GET_RATE_NOCACHE | CLK_IS_ROOT,
32768);
clk_register_fixed_rate(NULL, "clk_dummy", NULL, CLK_IS_ROOT, 0);
clk_register_fixed_factor(NULL, "ppll_95_85mhz", "osc_3_6864mhz",
0, 26, 1);
clk_register_fixed_factor(NULL, "ppll_147_46mhz", "osc_3_6864mhz",
0, 40, 1);
}
static void __init pxa25x_base_clocks_init(void)
{
pxa25x_register_plls();
pxa25x_register_core();
clk_register_clk_pxa25x_memory();
}
#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, "pxa25x-gpio", "osc_32_768khz"),
DUMMY_CLK(NULL, "pxa26x-gpio", "osc_32_768khz"),
DUMMY_CLK("GPIO11_CLK", NULL, "osc_3_6864mhz"),
DUMMY_CLK("GPIO12_CLK", NULL, "osc_32_768khz"),
DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
DUMMY_CLK("OSTIMER0", NULL, "osc_32_768khz"),
DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
};
static void __init pxa25x_dummy_clocks_init(void)
{
struct clk *clk;
struct dummy_clk *d;
const char *name;
int i;
/*
* All pinctrl logic has been wiped out of the clock driver, especially
* for gpio11 and gpio12 outputs. Machine code should ensure proper pin
* control (ie. pxa2xx_mfp_config() invocation).
*/
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);
}
}
int __init pxa25x_clocks_init(void)
{
pxa25x_base_clocks_init();
pxa25x_dummy_clocks_init();
return clk_pxa_cken_init(pxa25x_clocks, ARRAY_SIZE(pxa25x_clocks));
}
static void __init pxa25x_dt_clocks_init(struct device_node *np)
{
pxa25x_clocks_init();
clk_pxa_dt_common_init(np);
}
CLK_OF_DECLARE(pxa25x_clks, "marvell,pxa250-core-clocks",
pxa25x_dt_clocks_init);
......@@ -111,7 +111,7 @@ PARENTS(pxa27x_membus) = { "lcd_base", "lcd_base" };
PXA_CKEN_1RATE(dev_id, con_id, bit, parents, \
&CKEN, CKEN_ ## bit, CLK_IGNORE_UNUSED)
static struct pxa_clk_cken pxa27x_clocks[] = {
static struct desc_clk_cken pxa27x_clocks[] __initdata = {
PXA27X_PBUS_CKEN("pxa2xx-uart.0", NULL, FFUART, 2, 42, 1),
PXA27X_PBUS_CKEN("pxa2xx-uart.1", NULL, BTUART, 2, 42, 1),
PXA27X_PBUS_CKEN("pxa2xx-uart.2", NULL, STUART, 2, 42, 1),
......@@ -368,3 +368,10 @@ static int __init pxa27x_clocks_init(void)
return clk_pxa_cken_init(pxa27x_clocks, ARRAY_SIZE(pxa27x_clocks));
}
postcore_initcall(pxa27x_clocks_init);
static void __init pxa27x_dt_clocks_init(struct device_node *np)
{
pxa27x_clocks_init();
clk_pxa_dt_common_init(np);
}
CLK_OF_DECLARE(pxa_clks, "marvell,pxa270-clocks", pxa27x_dt_clocks_init);
......@@ -141,7 +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 *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_pll *pll = to_clk_pll(hw);
const struct pll_freq_tbl *f;
......
......@@ -368,16 +368,17 @@ 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 *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p_hw)
{
unsigned long clk_flags;
struct clk *p;
f = qcom_find_freq(f, rate);
if (!f)
return -EINVAL;
clk_flags = __clk_get_flags(hw->clk);
*p = clk_get_parent_by_index(hw->clk, f->src);
p = clk_get_parent_by_index(hw->clk, f->src);
if (clk_flags & CLK_SET_RATE_PARENT) {
rate = rate * f->pre_div;
if (f->n) {
......@@ -387,15 +388,16 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
rate = tmp;
}
} else {
rate = __clk_get_rate(*p);
rate = __clk_get_rate(p);
}
*p_hw = __clk_get_hw(p);
*p_rate = rate;
return f->freq;
}
static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
......@@ -403,7 +405,7 @@ static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
}
static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
......@@ -411,13 +413,15 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
}
static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p_hw)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
const struct freq_tbl *f = rcg->freq_tbl;
struct clk *p;
*p = clk_get_parent_by_index(hw->clk, f->src);
*p_rate = __clk_round_rate(*p, rate);
p = clk_get_parent_by_index(hw->clk, f->src);
*p_hw = __clk_get_hw(p);
*p_rate = __clk_round_rate(p, rate);
return *p_rate;
}
......
......@@ -175,16 +175,17 @@ clk_rcg2_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 *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p_hw)
{
unsigned long clk_flags;
struct clk *p;
f = qcom_find_freq(f, rate);
if (!f)
return -EINVAL;
clk_flags = __clk_get_flags(hw->clk);
*p = clk_get_parent_by_index(hw->clk, f->src);
p = clk_get_parent_by_index(hw->clk, f->src);
if (clk_flags & CLK_SET_RATE_PARENT) {
if (f->pre_div) {
rate /= 2;
......@@ -198,15 +199,16 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
rate = tmp;
}
} else {
rate = __clk_get_rate(*p);
rate = __clk_get_rate(p);
}
*p_hw = __clk_get_hw(p);
*p_rate = rate;
return f->freq;
}
static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
......@@ -359,7 +361,7 @@ 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 *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
const struct freq_tbl *f = rcg->freq_tbl;
......@@ -371,7 +373,7 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
u32 hid_div;
/* Force the correct parent */
*p = clk_get_parent_by_index(hw->clk, f->src);
*p = __clk_get_hw(clk_get_parent_by_index(hw->clk, f->src));
if (src_rate == 810000000)
frac = frac_table_810m;
......@@ -410,18 +412,20 @@ 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 *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p_hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
const struct freq_tbl *f = rcg->freq_tbl;
unsigned long parent_rate, div;
u32 mask = BIT(rcg->hid_width) - 1;
struct clk *p;
if (rate == 0)
return -EINVAL;
*p = clk_get_parent_by_index(hw->clk, f->src);
*p_rate = parent_rate = __clk_round_rate(*p, rate);
p = clk_get_parent_by_index(hw->clk, f->src);
*p_hw = __clk_get_hw(p);
*p_rate = parent_rate = __clk_round_rate(p, rate);
div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
div = min_t(u32, div, mask);
......@@ -472,14 +476,16 @@ static const struct frac_entry frac_table_pixel[] = {
};
static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *p_rate, struct clk **p)
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
unsigned long request, src_rate;
int delta = 100000;
const struct freq_tbl *f = rcg->freq_tbl;
const struct frac_entry *frac = frac_table_pixel;
struct clk *parent = *p = clk_get_parent_by_index(hw->clk, f->src);
struct clk *parent = clk_get_parent_by_index(hw->clk, f->src);
*p = __clk_get_hw(parent);
for (; frac->num; frac++) {
request = (rate * frac->den) / frac->num;
......
......@@ -6,6 +6,7 @@ obj-y += clk-rockchip.o
obj-y += clk.o
obj-y += clk-pll.o
obj-y += clk-cpu.o
obj-y += clk-mmc-phase.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
obj-y += clk-rk3188.o
......
/*
* Copyright 2014 Google, Inc
* Author: Alexandru M Stan <amstan@chromium.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include "clk.h"
struct rockchip_mmc_clock {
struct clk_hw hw;
void __iomem *reg;
int id;
int shift;
};
#define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
#define RK3288_MMC_CLKGEN_DIV 2
static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
unsigned long parent_rate)
{
return parent_rate / RK3288_MMC_CLKGEN_DIV;
}
#define ROCKCHIP_MMC_DELAY_SEL BIT(10)
#define ROCKCHIP_MMC_DEGREE_MASK 0x3
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
#define PSECS_PER_SEC 1000000000000LL
/*
* Each fine delay is between 40ps-80ps. Assume each fine delay is 60ps to
* simplify calculations. So 45degs could be anywhere between 33deg and 66deg.
*/
#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
static int rockchip_mmc_get_phase(struct clk_hw *hw)
{
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
unsigned long rate = clk_get_rate(hw->clk);
u32 raw_value;
u16 degrees;
u32 delay_num = 0;
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
/* degrees/delaynum * 10000 */
unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
36 * (rate / 1000000);
delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
degrees += delay_num * factor / 10000;
}
return degrees % 360;
}
static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
{
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
unsigned long rate = clk_get_rate(hw->clk);
u8 nineties, remainder;
u8 delay_num;
u32 raw_value;
u64 delay;
/* allow 22 to be 22.5 */
degrees++;
/* floor to 22.5 increment */
degrees -= ((degrees) * 10 % 225) / 10;
nineties = degrees / 90;
/* 22.5 multiples */
remainder = (degrees % 90) / 22;
delay = PSECS_PER_SEC;
do_div(delay, rate);
/* / 360 / 22.5 */
do_div(delay, 16);
do_div(delay, ROCKCHIP_MMC_DELAY_ELEMENT_PSEC);
delay *= remainder;
delay_num = (u8) min(delay, 255ULL);
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
raw_value |= nineties;
writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg);
pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
__clk_get_name(hw->clk), degrees, delay_num,
mmc_clock->reg, raw_value>>(mmc_clock->shift),
rockchip_mmc_get_phase(hw)
);
return 0;
}
static const struct clk_ops rockchip_mmc_clk_ops = {
.recalc_rate = rockchip_mmc_recalc,
.get_phase = rockchip_mmc_get_phase,
.set_phase = rockchip_mmc_set_phase,
};
struct clk *rockchip_clk_register_mmc(const char *name,
const char **parent_names, u8 num_parents,
void __iomem *reg, int shift)
{
struct clk_init_data init;
struct rockchip_mmc_clock *mmc_clock;
struct clk *clk;
mmc_clock = kmalloc(sizeof(*mmc_clock), GFP_KERNEL);
if (!mmc_clock)
return NULL;
init.num_parents = num_parents;
init.parent_names = parent_names;
init.ops = &rockchip_mmc_clk_ops;
mmc_clock->hw.init = &init;
mmc_clock->reg = reg;
mmc_clock->shift = shift;
if (name)
init.name = name;
clk = clk_register(NULL, &mmc_clock->hw);
if (IS_ERR(clk))
goto err_free;
return clk;
err_free:
kfree(mmc_clock);
return NULL;
}
......@@ -39,6 +39,7 @@ struct rockchip_clk_pll {
int lock_offset;
unsigned int lock_shift;
enum rockchip_pll_type type;
u8 flags;
const struct rockchip_pll_rate_table *rate_table;
unsigned int rate_count;
spinlock_t *lock;
......@@ -257,6 +258,55 @@ static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)
return !(pllcon & RK3066_PLLCON3_PWRDOWN);
}
static void rockchip_rk3066_pll_init(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
const struct rockchip_pll_rate_table *rate;
unsigned int nf, nr, no, bwadj;
unsigned long drate;
u32 pllcon;
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
return;
drate = __clk_get_rate(hw->clk);
rate = rockchip_get_pll_settings(pll, drate);
/* when no rate setting for the current rate, rely on clk_set_rate */
if (!rate)
return;
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1;
no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1;
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
bwadj = (pllcon >> RK3066_PLLCON2_BWADJ_SHIFT) & RK3066_PLLCON2_BWADJ_MASK;
pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), bwadj(%d:%d)\n",
__func__, __clk_get_name(hw->clk), drate, rate->nr, nr,
rate->no, no, rate->nf, nf, rate->bwadj, bwadj);
if (rate->nr != nr || rate->no != no || rate->nf != nf
|| rate->bwadj != bwadj) {
struct clk *parent = __clk_get_parent(hw->clk);
unsigned long prate;
if (!parent) {
pr_warn("%s: parent of %s not available\n",
__func__, __clk_get_name(hw->clk));
return;
}
pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
__func__, __clk_get_name(hw->clk));
prate = __clk_get_rate(parent);
rockchip_rk3066_pll_set_rate(hw, drate, prate);
}
}
static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
.recalc_rate = rockchip_rk3066_pll_recalc_rate,
.enable = rockchip_rk3066_pll_enable,
......@@ -271,6 +321,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
.enable = rockchip_rk3066_pll_enable,
.disable = rockchip_rk3066_pll_disable,
.is_enabled = rockchip_rk3066_pll_is_enabled,
.init = rockchip_rk3066_pll_init,
};
/*
......@@ -282,7 +333,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
void __iomem *base, int con_offset, int grf_lock_offset,
int lock_shift, int mode_offset, int mode_shift,
struct rockchip_pll_rate_table *rate_table,
spinlock_t *lock)
u8 clk_pll_flags, spinlock_t *lock)
{
const char *pll_parents[3];
struct clk_init_data init;
......@@ -345,8 +396,22 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
pll->reg_base = base + con_offset;
pll->lock_offset = grf_lock_offset;
pll->lock_shift = lock_shift;
pll->flags = clk_pll_flags;
pll->lock = lock;
/* create the mux on top of the real pll */
pll->pll_mux_ops = &clk_mux_ops;
pll_mux = &pll->pll_mux;
pll_mux->reg = base + mode_offset;
pll_mux->shift = mode_shift;
pll_mux->mask = PLL_MODE_MASK;
pll_mux->flags = 0;
pll_mux->lock = lock;
pll_mux->hw.init = &init;
if (pll_type == pll_rk3066)
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
pll_clk = clk_register(NULL, &pll->hw);
if (IS_ERR(pll_clk)) {
pr_err("%s: failed to register pll clock %s : %ld\n",
......@@ -355,10 +420,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
goto err_pll;
}
/* create the mux on top of the real pll */
pll->pll_mux_ops = &clk_mux_ops;
pll_mux = &pll->pll_mux;
/* the actual muxing is xin24m, pll-output, xin32k */
pll_parents[0] = parent_names[0];
pll_parents[1] = pll_name;
......@@ -370,16 +431,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
init.parent_names = pll_parents;
init.num_parents = ARRAY_SIZE(pll_parents);
pll_mux->reg = base + mode_offset;
pll_mux->shift = mode_shift;
pll_mux->mask = PLL_MODE_MASK;
pll_mux->flags = 0;
pll_mux->lock = lock;
pll_mux->hw.init = &init;
if (pll_type == pll_rk3066)
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
mux_clk = clk_register(NULL, &pll_mux->hw);
if (IS_ERR(mux_clk))
goto err_mux;
......
This diff is collapsed.
This diff is collapsed.
......@@ -197,7 +197,8 @@ void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
list->parent_names, list->num_parents,
reg_base, list->con_offset, grf_lock_offset,
list->lock_shift, list->mode_offset,
list->mode_shift, list->rate_table, &clk_lock);
list->mode_shift, list->rate_table,
list->pll_flags, &clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
......@@ -244,9 +245,6 @@ void __init rockchip_clk_register_branches(
list->div_flags, &clk_lock);
break;
case branch_fraction_divider:
/* keep all gates untouched for now */
flags |= CLK_IGNORE_UNUSED;
clk = rockchip_clk_register_frac_branch(list->name,
list->parent_names, list->num_parents,
reg_base, list->muxdiv_offset, list->div_flags,
......@@ -256,18 +254,12 @@ void __init rockchip_clk_register_branches(
case branch_gate:
flags |= CLK_SET_RATE_PARENT;
/* keep all gates untouched for now */
flags |= CLK_IGNORE_UNUSED;
clk = clk_register_gate(NULL, list->name,
list->parent_names[0], flags,
reg_base + list->gate_offset,
list->gate_shift, list->gate_flags, &clk_lock);
break;
case branch_composite:
/* keep all gates untouched for now */
flags |= CLK_IGNORE_UNUSED;
clk = rockchip_clk_register_branch(list->name,
list->parent_names, list->num_parents,
reg_base, list->muxdiv_offset, list->mux_shift,
......@@ -277,6 +269,14 @@ void __init rockchip_clk_register_branches(
list->gate_offset, list->gate_shift,
list->gate_flags, flags, &clk_lock);
break;
case branch_mmc:
clk = rockchip_clk_register_mmc(
list->name,
list->parent_names, list->num_parents,
reg_base + list->muxdiv_offset,
list->div_shift
);
break;
}
/* none of the cases above matched */
......
......@@ -48,6 +48,14 @@
#define RK3288_GLB_SRST_SND 0x1b4
#define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8)
#define RK3288_MISC_CON 0x1e8
#define RK3288_SDMMC_CON0 0x200
#define RK3288_SDMMC_CON1 0x204
#define RK3288_SDIO0_CON0 0x208
#define RK3288_SDIO0_CON1 0x20c
#define RK3288_SDIO1_CON0 0x210
#define RK3288_SDIO1_CON1 0x214
#define RK3288_EMMC_CON0 0x218
#define RK3288_EMMC_CON1 0x21c
enum rockchip_pll_type {
pll_rk3066,
......@@ -62,6 +70,15 @@ enum rockchip_pll_type {
.bwadj = (_nf >> 1), \
}
#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \
{ \
.rate = _rate##U, \
.nr = _nr, \
.nf = _nf, \
.no = _no, \
.bwadj = _bw, \
}
struct rockchip_pll_rate_table {
unsigned long rate;
unsigned int nr;
......@@ -81,7 +98,12 @@ struct rockchip_pll_rate_table {
* @mode_shift: offset inside the mode-register for the mode of this pll.
* @lock_shift: offset inside the lock register for the lock status.
* @type: Type of PLL to be registered.
* @pll_flags: hardware-specific flags
* @rate_table: Table of usable pll rates
*
* Flags:
* ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
* rate_table parameters and ajust them if necessary.
*/
struct rockchip_pll_clock {
unsigned int id;
......@@ -94,11 +116,14 @@ struct rockchip_pll_clock {
int mode_shift;
int lock_shift;
enum rockchip_pll_type type;
u8 pll_flags;
struct rockchip_pll_rate_table *rate_table;
};
#define ROCKCHIP_PLL_SYNC_RATE BIT(0)
#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \
_lshift, _rtable) \
_lshift, _pflags, _rtable) \
{ \
.id = _id, \
.type = _type, \
......@@ -110,6 +135,7 @@ struct rockchip_pll_clock {
.mode_offset = _mode, \
.mode_shift = _mshift, \
.lock_shift = _lshift, \
.pll_flags = _pflags, \
.rate_table = _rtable, \
}
......@@ -118,7 +144,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
void __iomem *base, int con_offset, int grf_lock_offset,
int lock_shift, int reg_mode, int mode_shift,
struct rockchip_pll_rate_table *rate_table,
spinlock_t *lock);
u8 clk_pll_flags, spinlock_t *lock);
struct rockchip_cpuclk_clksel {
int reg;
......@@ -152,6 +178,10 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
const struct rockchip_cpuclk_rate_table *rates,
int nrates, void __iomem *reg_base, spinlock_t *lock);
struct clk *rockchip_clk_register_mmc(const char *name,
const char **parent_names, u8 num_parents,
void __iomem *reg, int shift);
#define PNAME(x) static const char *x[] __initconst
enum rockchip_clk_branch_type {
......@@ -160,6 +190,7 @@ enum rockchip_clk_branch_type {
branch_divider,
branch_fraction_divider,
branch_gate,
branch_mmc,
};
struct rockchip_clk_branch {
......@@ -352,6 +383,16 @@ struct rockchip_clk_branch {
.gate_flags = gf, \
}
#define MMC(_id, cname, pname, offset, shift) \
{ \
.id = _id, \
.branch_type = branch_mmc, \
.name = cname, \
.parent_names = (const char *[]){ pname }, \
.num_parents = 1, \
.muxdiv_offset = offset, \
.div_shift = shift, \
}
void rockchip_clk_init(struct device_node *np, void __iomem *base,
unsigned long nr_clks);
......
......@@ -5,6 +5,7 @@
obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
obj-$(CONFIG_SOC_EXYNOS4415) += clk-exynos4415.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o
obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
......@@ -12,6 +13,7 @@ obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_ARCH_EXYNOS7) += clk-exynos7.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
......
This diff is collapsed.
......@@ -505,7 +505,7 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata
/* fixed rate clocks generated inside the soc */
static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", "hdmi", 0, 27000000),
FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -33,6 +33,10 @@ enum samsung_pll_type {
pll_s3c2440_mpll,
pll_2550xx,
pll_2650xx,
pll_1450x,
pll_1451x,
pll_1452x,
pll_1460x,
};
#define PLL_35XX_RATE(_rate, _m, _p, _s) \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -7,6 +7,7 @@ obj-y += clk-a10-hosc.o
obj-y += clk-a20-gmac.o
obj-y += clk-mod0.o
obj-y += clk-sun8i-mbus.o
obj-y += clk-sun9i-core.o
obj-$(CONFIG_MFD_SUN6I_PRCM) += \
clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
......
......@@ -53,6 +53,11 @@ static DEFINE_SPINLOCK(gmac_lock);
#define SUN7I_A20_GMAC_MASK 0x3
#define SUN7I_A20_GMAC_PARENTS 2
static u32 sun7i_a20_gmac_mux_table[SUN7I_A20_GMAC_PARENTS] = {
0x00, /* Select mii_phy_tx_clk */
0x02, /* Select gmac_int_tx_clk */
};
static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
{
struct clk *clk;
......@@ -90,7 +95,7 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
gate->lock = &gmac_lock;
mux->reg = reg;
mux->mask = SUN7I_A20_GMAC_MASK;
mux->flags = CLK_MUX_INDEX_BIT;
mux->table = sun7i_a20_gmac_mux_table;
mux->lock = &gmac_lock;
clk = clk_register_composite(NULL, clk_name,
......
......@@ -81,7 +81,7 @@ 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 *best_parent_rate,
struct clk **best_parent_p)
struct clk_hw **best_parent_p)
{
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
......@@ -108,7 +108,7 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
}
if (best_parent)
*best_parent_p = best_parent;
*best_parent_p = __clk_get_hw(best_parent);
*best_parent_rate = best;
return best_child_rate;
......@@ -224,7 +224,7 @@ struct clk * __init sunxi_factors_register(struct device_node *node,
/* set up gate properties */
mux->reg = reg;
mux->shift = data->mux;
mux->mask = SUNXI_FACTORS_MUX_MASK;
mux->mask = data->muxmask;
mux->lock = factors->lock;
mux_hw = &mux->hw;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment