diff options
136 files changed, 7164 insertions, 1122 deletions
diff --git a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt new file mode 100644 index 000000000000..8968371d84e2 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt | |||
@@ -0,0 +1,35 @@ | |||
1 | Marvell Armada AP806 System Controller | ||
2 | ====================================== | ||
3 | |||
4 | The AP806 is one of the two core HW blocks of the Marvell Armada 7K/8K | ||
5 | SoCs. It contains a system controller, which provides a number | ||
6 | registers giving access to numerous features: clocks, pin-muxing and | ||
7 | many other SoC configuration items. This DT binding allows to describe | ||
8 | this system controller. | ||
9 | |||
10 | The Device Tree node representing the AP806 system controller provides | ||
11 | a number of clocks: | ||
12 | |||
13 | - 0: clock of CPU cluster 0 | ||
14 | - 1: clock of CPU cluster 1 | ||
15 | - 2: fixed PLL at 1200 Mhz | ||
16 | - 3: MSS clock, derived from the fixed PLL | ||
17 | |||
18 | Required properties: | ||
19 | |||
20 | - compatible: must be: | ||
21 | "marvell,ap806-system-controller", "syscon" | ||
22 | - reg: register area of the AP806 system controller | ||
23 | - #clock-cells: must be set to 1 | ||
24 | - clock-output-names: must be defined to: | ||
25 | "ap-cpu-cluster-0", "ap-cpu-cluster-1", "ap-fixed", "ap-mss" | ||
26 | |||
27 | Example: | ||
28 | |||
29 | syscon: system-controller@6f4000 { | ||
30 | compatible = "marvell,ap806-system-controller", "syscon"; | ||
31 | #clock-cells = <1>; | ||
32 | clock-output-names = "ap-cpu-cluster-0", "ap-cpu-cluster-1", | ||
33 | "ap-fixed", "ap-mss"; | ||
34 | reg = <0x6f4000 0x1000>; | ||
35 | }; | ||
diff --git a/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt new file mode 100644 index 000000000000..30c546900b60 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt | |||
@@ -0,0 +1,83 @@ | |||
1 | Marvell Armada CP110 System Controller 0 | ||
2 | ======================================== | ||
3 | |||
4 | The CP110 is one of the two core HW blocks of the Marvell Armada 7K/8K | ||
5 | SoCs. It contains two sets of system control registers, System | ||
6 | Controller 0 and System Controller 1. This Device Tree binding allows | ||
7 | to describe the first system controller, which provides registers to | ||
8 | configure various aspects of the SoC. | ||
9 | |||
10 | The Device Tree node representing this System Controller 0 provides a | ||
11 | number of clocks: | ||
12 | |||
13 | - a set of core clocks | ||
14 | - a set of gatable clocks | ||
15 | |||
16 | Those clocks can be referenced by other Device Tree nodes using two | ||
17 | cells: | ||
18 | - The first cell must be 0 or 1. 0 for the core clocks and 1 for the | ||
19 | gatable clocks. | ||
20 | - The second cell identifies the particular core clock or gatable | ||
21 | clocks. | ||
22 | |||
23 | The following clocks are available: | ||
24 | - Core clocks | ||
25 | - 0 0 APLL | ||
26 | - 0 1 PPv2 core | ||
27 | - 0 2 EIP | ||
28 | - 0 3 Core | ||
29 | - 0 4 NAND core | ||
30 | - Gatable clocks | ||
31 | - 1 0 Audio | ||
32 | - 1 1 Comm Unit | ||
33 | - 1 2 NAND | ||
34 | - 1 3 PPv2 | ||
35 | - 1 4 SDIO | ||
36 | - 1 5 MG Domain | ||
37 | - 1 6 MG Core | ||
38 | - 1 7 XOR1 | ||
39 | - 1 8 XOR0 | ||
40 | - 1 9 GOP DP | ||
41 | - 1 11 PCIe x1 0 | ||
42 | - 1 12 PCIe x1 1 | ||
43 | - 1 13 PCIe x4 | ||
44 | - 1 14 PCIe / XOR | ||
45 | - 1 15 SATA | ||
46 | - 1 16 SATA USB | ||
47 | - 1 17 Main | ||
48 | - 1 18 SD/MMC | ||
49 | - 1 21 Slow IO (SPI, NOR, BootROM, I2C, UART) | ||
50 | - 1 22 USB3H0 | ||
51 | - 1 23 USB3H1 | ||
52 | - 1 24 USB3 Device | ||
53 | - 1 25 EIP150 | ||
54 | - 1 26 EIP197 | ||
55 | |||
56 | Required properties: | ||
57 | |||
58 | - compatible: must be: | ||
59 | "marvell,cp110-system-controller0", "syscon"; | ||
60 | - reg: register area of the CP110 system controller 0 | ||
61 | - #clock-cells: must be set to 2 | ||
62 | - core-clock-output-names must be set to: | ||
63 | "cpm-apll", "cpm-ppv2-core", "cpm-eip", "cpm-core", "cpm-nand-core" | ||
64 | - gate-clock-output-names must be set to: | ||
65 | "cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio", | ||
66 | "cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none", | ||
67 | "cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata", | ||
68 | "cpm-sata-usb", "cpm-main", "cpm-sd-mmc", "none", "none", "cpm-slow-io", | ||
69 | "cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197"; | ||
70 | |||
71 | Example: | ||
72 | |||
73 | cpm_syscon0: system-controller@440000 { | ||
74 | compatible = "marvell,cp110-system-controller0", "syscon"; | ||
75 | reg = <0x440000 0x1000>; | ||
76 | #clock-cells = <2>; | ||
77 | core-clock-output-names = "cpm-apll", "cpm-ppv2-core", "cpm-eip", "cpm-core", "cpm-nand-core"; | ||
78 | gate-clock-output-names = "cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio", | ||
79 | "cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none", | ||
80 | "cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata", | ||
81 | "cpm-sata-usb", "cpm-main", "cpm-sd-mmc", "none", "none", "cpm-slow-io", | ||
82 | "cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197"; | ||
83 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/artpec6.txt b/Documentation/devicetree/bindings/clock/artpec6.txt new file mode 100644 index 000000000000..dff9cdf0009c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/artpec6.txt | |||
@@ -0,0 +1,41 @@ | |||
1 | * Clock bindings for Axis ARTPEC-6 chip | ||
2 | |||
3 | The bindings are based on the clock provider binding in | ||
4 | Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
5 | |||
6 | External clocks: | ||
7 | ---------------- | ||
8 | |||
9 | There are two external inputs to the main clock controller which should be | ||
10 | provided using the common clock bindings. | ||
11 | - "sys_refclk": External 50 Mhz oscillator (required) | ||
12 | - "i2s_refclk": Alternate audio reference clock (optional). | ||
13 | |||
14 | Main clock controller | ||
15 | --------------------- | ||
16 | |||
17 | Required properties: | ||
18 | - #clock-cells: Should be <1> | ||
19 | See dt-bindings/clock/axis,artpec6-clkctrl.h for the list of valid identifiers. | ||
20 | - compatible: Should be "axis,artpec6-clkctrl" | ||
21 | - reg: Must contain the base address and length of the system controller | ||
22 | - clocks: Must contain a phandle entry for each clock in clock-names | ||
23 | - clock-names: Must include the external oscillator ("sys_refclk"). Optional | ||
24 | ones are the audio reference clock ("i2s_refclk") and the audio fractional | ||
25 | dividers ("frac_clk0" and "frac_clk1"). | ||
26 | |||
27 | Examples: | ||
28 | |||
29 | ext_clk: ext_clk { | ||
30 | #clock-cells = <0>; | ||
31 | compatible = "fixed-clock"; | ||
32 | clock-frequency = <50000000>; | ||
33 | }; | ||
34 | |||
35 | clkctrl: clkctrl@f8000000 { | ||
36 | #clock-cells = <1>; | ||
37 | compatible = "axis,artpec6-clkctrl"; | ||
38 | reg = <0xf8000000 0x48>; | ||
39 | clocks = <&ext_clk>; | ||
40 | clock-names = "sys_refclk"; | ||
41 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt b/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt new file mode 100644 index 000000000000..5ffc8df7e6da --- /dev/null +++ b/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt | |||
@@ -0,0 +1,25 @@ | |||
1 | Binding for the AXS10X I2S PLL clock | ||
2 | |||
3 | This binding uses the common clock binding[1]. | ||
4 | |||
5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: shall be "snps,axs10x-i2s-pll-clock" | ||
9 | - reg : address and length of the I2S PLL register set. | ||
10 | - clocks: shall be the input parent clock phandle for the PLL. | ||
11 | - #clock-cells: from common clock binding; Should always be set to 0. | ||
12 | |||
13 | Example: | ||
14 | pll_clock: pll_clock { | ||
15 | compatible = "fixed-clock"; | ||
16 | clock-frequency = <27000000>; | ||
17 | #clock-cells = <0>; | ||
18 | }; | ||
19 | |||
20 | i2s_clock@100a0 { | ||
21 | compatible = "snps,axs10x-i2s-pll-clock"; | ||
22 | reg = <0x100a0 0x10>; | ||
23 | clocks = <&pll_clock>; | ||
24 | #clock-cells = <0>; | ||
25 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/hi3519-crg.txt b/Documentation/devicetree/bindings/clock/hi3519-crg.txt new file mode 100644 index 000000000000..acd1f235d548 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/hi3519-crg.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | * Hisilicon Hi3519 Clock and Reset Generator(CRG) | ||
2 | |||
3 | The Hi3519 CRG module provides clock and reset signals to various | ||
4 | controllers within the SoC. | ||
5 | |||
6 | This binding uses the following bindings: | ||
7 | Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
8 | Documentation/devicetree/bindings/reset/reset.txt | ||
9 | |||
10 | Required Properties: | ||
11 | |||
12 | - compatible: should be one of the following. | ||
13 | - "hisilicon,hi3519-crg" - controller compatible with Hi3519 SoC. | ||
14 | |||
15 | - reg: physical base address of the controller and length of memory mapped | ||
16 | region. | ||
17 | |||
18 | - #clock-cells: should be 1. | ||
19 | |||
20 | Each clock is assigned an identifier and client nodes use this identifier | ||
21 | to specify the clock which they consume. | ||
22 | |||
23 | All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>. | ||
24 | |||
25 | - #reset-cells: should be 2. | ||
26 | |||
27 | A reset signal can be controlled by writing a bit register in the CRG module. | ||
28 | The reset specifier consists of two cells. The first cell represents the | ||
29 | register offset relative to the base address. The second cell represents the | ||
30 | bit index in the register. | ||
31 | |||
32 | Example: CRG nodes | ||
33 | CRG: clock-reset-controller@12010000 { | ||
34 | compatible = "hisilicon,hi3519-crg"; | ||
35 | reg = <0x12010000 0x10000>; | ||
36 | #clock-cells = <1>; | ||
37 | #reset-cells = <2>; | ||
38 | }; | ||
39 | |||
40 | Example: consumer nodes | ||
41 | i2c0: i2c@12110000 { | ||
42 | compatible = "hisilicon,hi3519-i2c"; | ||
43 | reg = <0x12110000 0x1000>; | ||
44 | clocks = <&CRG HI3519_I2C0_RST>; | ||
45 | resets = <&CRG 0xe4 0>; | ||
46 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/imx35-clock.txt b/Documentation/devicetree/bindings/clock/imx35-clock.txt index a70356452a82..f49783213c56 100644 --- a/Documentation/devicetree/bindings/clock/imx35-clock.txt +++ b/Documentation/devicetree/bindings/clock/imx35-clock.txt | |||
@@ -94,6 +94,7 @@ clocks and IDs. | |||
94 | csi_sel 79 | 94 | csi_sel 79 |
95 | iim_gate 80 | 95 | iim_gate 80 |
96 | gpu2d_gate 81 | 96 | gpu2d_gate 81 |
97 | ckli_gate 82 | ||
97 | 98 | ||
98 | Examples: | 99 | Examples: |
99 | 100 | ||
diff --git a/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt b/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt new file mode 100644 index 000000000000..208cca6ac4ec --- /dev/null +++ b/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt | |||
@@ -0,0 +1,35 @@ | |||
1 | Oxford Semiconductor OXNAS SoC Family Standard Clocks | ||
2 | ================================================ | ||
3 | |||
4 | Please also refer to clock-bindings.txt in this directory for common clock | ||
5 | bindings usage. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: Should be "oxsemi,ox810se-stdclk" | ||
9 | - #clock-cells: 1, see below | ||
10 | |||
11 | Parent node should have the following properties : | ||
12 | - compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd" | ||
13 | |||
14 | For OX810SE, the clock indices are : | ||
15 | - 0: LEON | ||
16 | - 1: DMA_SGDMA | ||
17 | - 2: CIPHER | ||
18 | - 3: SATA | ||
19 | - 4: AUDIO | ||
20 | - 5: USBMPH | ||
21 | - 6: ETHA | ||
22 | - 7: PCIA | ||
23 | - 8: NAND | ||
24 | |||
25 | example: | ||
26 | |||
27 | sys: sys-ctrl@000000 { | ||
28 | compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"; | ||
29 | reg = <0x000000 0x100000>; | ||
30 | |||
31 | stdclk: stdclk { | ||
32 | compatible = "oxsemi,ox810se-stdclk"; | ||
33 | #clock-cells = <1>; | ||
34 | }; | ||
35 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt new file mode 100644 index 000000000000..3888dd33fcbd --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | * Rockchip RK3399 Clock and Reset Unit | ||
2 | |||
3 | The RK3399 clock controller generates and supplies clock to various | ||
4 | controllers within the SoC and also implements a reset controller for SoC | ||
5 | peripherals. | ||
6 | |||
7 | Required Properties: | ||
8 | |||
9 | - compatible: PMU for CRU should be "rockchip,rk3399-pmucru" | ||
10 | - compatible: CRU should be "rockchip,rk3399-cru" | ||
11 | - reg: physical base address of the controller and length of memory mapped | ||
12 | region. | ||
13 | - #clock-cells: should be 1. | ||
14 | - #reset-cells: should be 1. | ||
15 | |||
16 | Each clock is assigned an identifier and client nodes can use this identifier | ||
17 | to specify the clock which they consume. All available clocks are defined as | ||
18 | preprocessor macros in the dt-bindings/clock/rk3399-cru.h headers and can be | ||
19 | used in device tree sources. Similar macros exist for the reset sources in | ||
20 | these files. | ||
21 | |||
22 | External clocks: | ||
23 | |||
24 | There are several clocks that are generated outside the SoC. It is expected | ||
25 | that they are defined using standard clock bindings with following | ||
26 | clock-output-names: | ||
27 | - "xin24m" - crystal input - required, | ||
28 | - "xin32k" - rtc clock - optional, | ||
29 | - "clkin_gmac" - external GMAC clock - optional, | ||
30 | - "clkin_i2s" - external I2S clock - optional, | ||
31 | - "pclkin_cif" - external ISP clock - optional, | ||
32 | - "clk_usbphy0_480m" - output clock of the pll in the usbphy0 | ||
33 | - "clk_usbphy1_480m" - output clock of the pll in the usbphy1 | ||
34 | |||
35 | Example: Clock controller node: | ||
36 | |||
37 | pmucru: pmu-clock-controller@ff750000 { | ||
38 | compatible = "rockchip,rk3399-pmucru"; | ||
39 | reg = <0x0 0xff750000 0x0 0x1000>; | ||
40 | #clock-cells = <1>; | ||
41 | #reset-cells = <1>; | ||
42 | }; | ||
43 | |||
44 | cru: clock-controller@ff760000 { | ||
45 | compatible = "rockchip,rk3399-cru"; | ||
46 | reg = <0x0 0xff760000 0x0 0x1000>; | ||
47 | #clock-cells = <1>; | ||
48 | #reset-cells = <1>; | ||
49 | }; | ||
50 | |||
51 | Example: UART controller node that consumes the clock generated by the clock | ||
52 | controller: | ||
53 | |||
54 | uart0: serial@ff1a0000 { | ||
55 | compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; | ||
56 | reg = <0x0 0xff180000 0x0 0x100>; | ||
57 | clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; | ||
58 | clock-names = "baudclk", "apb_pclk"; | ||
59 | interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; | ||
60 | reg-shift = <2>; | ||
61 | reg-io-width = <4>; | ||
62 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index 834436fbe83d..8f7619d8c8d8 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
@@ -10,6 +10,7 @@ Required properties: | |||
10 | "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 | 10 | "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 |
11 | "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 | 11 | "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 |
12 | "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 | 12 | "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 |
13 | "allwinner,sun4i-a10-pll3-clk" - for the video PLL clock on A10 | ||
13 | "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 | 14 | "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 |
14 | "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock | 15 | "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock |
15 | "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock | 16 | "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock |
@@ -63,7 +64,9 @@ Required properties: | |||
63 | "allwinner,sun8i-a83t-bus-gates-clk" - for the bus gates on A83T | 64 | "allwinner,sun8i-a83t-bus-gates-clk" - for the bus gates on A83T |
64 | "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 | 65 | "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 |
65 | "allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80 | 66 | "allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80 |
67 | "allwinner,sun4i-a10-display-clk" - for the display clocks on the A10 | ||
66 | "allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10 | 68 | "allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10 |
69 | "allwinner,sun5i-a13-dram-gates-clk" - for the DRAM gates on A13 | ||
67 | "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 | 70 | "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 |
68 | "allwinner,sun4i-a10-mmc-clk" - for the MMC clock | 71 | "allwinner,sun4i-a10-mmc-clk" - for the MMC clock |
69 | "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 | 72 | "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 |
@@ -73,6 +76,8 @@ Required properties: | |||
73 | "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 | 76 | "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 |
74 | "allwinner,sun7i-a20-out-clk" - for the external output clocks | 77 | "allwinner,sun7i-a20-out-clk" - for the external output clocks |
75 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 | 78 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 |
79 | "allwinner,sun4i-a10-tcon-ch0-clk" - for the TCON channel 0 clock on the A10 | ||
80 | "allwinner,sun4i-a10-tcon-ch1-clk" - for the TCON channel 1 clock on the A10 | ||
76 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 | 81 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 |
77 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 | 82 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 |
78 | "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 | 83 | "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 |
@@ -81,6 +86,7 @@ Required properties: | |||
81 | "allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80 | 86 | "allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80 |
82 | "allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80 | 87 | "allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80 |
83 | "allwinner,sun4i-a10-ve-clk" - for the Video Engine clock | 88 | "allwinner,sun4i-a10-ve-clk" - for the Video Engine clock |
89 | "allwinner,sun6i-a31-display-clk" - for the display clocks | ||
84 | 90 | ||
85 | Required properties for all clocks: | 91 | Required properties for all clocks: |
86 | - reg : shall be the control register address for the clock. | 92 | - reg : shall be the control register address for the clock. |
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 6c4478ce582d..76a6c0a70dee 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt | |||
@@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer). | |||
236 | CLOCK | 236 | CLOCK |
237 | devm_clk_get() | 237 | devm_clk_get() |
238 | devm_clk_put() | 238 | devm_clk_put() |
239 | devm_clk_hw_register() | ||
239 | 240 | ||
240 | DMA | 241 | DMA |
241 | dmam_alloc_coherent() | 242 | dmam_alloc_coherent() |
diff --git a/MAINTAINERS b/MAINTAINERS index 2f66ca77f7af..e8408315a696 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -977,7 +977,7 @@ S: Maintained | |||
977 | L: linux-arm-kernel@axis.com | 977 | L: linux-arm-kernel@axis.com |
978 | F: arch/arm/mach-artpec | 978 | F: arch/arm/mach-artpec |
979 | F: arch/arm/boot/dts/artpec6* | 979 | F: arch/arm/boot/dts/artpec6* |
980 | F: drivers/clk/clk-artpec6.c | 980 | F: drivers/clk/axis |
981 | 981 | ||
982 | ARM/ASPEED MACHINE SUPPORT | 982 | ARM/ASPEED MACHINE SUPPORT |
983 | M: Joel Stanley <joel@jms.id.au> | 983 | M: Joel Stanley <joel@jms.id.au> |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 90518cd7fc9c..53ddba26578c 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -200,6 +200,12 @@ config COMMON_CLK_PXA | |||
200 | config COMMON_CLK_PIC32 | 200 | config COMMON_CLK_PIC32 |
201 | def_bool COMMON_CLK && MACH_PIC32 | 201 | def_bool COMMON_CLK && MACH_PIC32 |
202 | 202 | ||
203 | config COMMON_CLK_OXNAS | ||
204 | bool "Clock driver for the OXNAS SoC Family" | ||
205 | select MFD_SYSCON | ||
206 | ---help--- | ||
207 | Support for the OXNAS SoC Family clocks. | ||
208 | |||
203 | source "drivers/clk/bcm/Kconfig" | 209 | source "drivers/clk/bcm/Kconfig" |
204 | source "drivers/clk/hisilicon/Kconfig" | 210 | source "drivers/clk/hisilicon/Kconfig" |
205 | source "drivers/clk/mvebu/Kconfig" | 211 | source "drivers/clk/mvebu/Kconfig" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18e64bbeeaf4..dcc5e698ff6d 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o | |||
33 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o | 33 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o |
34 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o | 34 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o |
35 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o | 35 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o |
36 | obj-$(CONFIG_COMMON_CLK_OXNAS) += clk-oxnas.o | ||
36 | obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o | 37 | obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o |
37 | obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o | 38 | obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o |
38 | obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o | 39 | obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o |
@@ -51,6 +52,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | |||
51 | obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o | 52 | obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o |
52 | obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o | 53 | obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o |
53 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ | 54 | obj-$(CONFIG_COMMON_CLK_AT91) += at91/ |
55 | obj-$(CONFIG_ARCH_ARTPEC) += axis/ | ||
54 | obj-y += bcm/ | 56 | obj-y += bcm/ |
55 | obj-$(CONFIG_ARCH_BERLIN) += berlin/ | 57 | obj-$(CONFIG_ARCH_BERLIN) += berlin/ |
56 | obj-$(CONFIG_ARCH_HISI) += hisilicon/ | 58 | obj-$(CONFIG_ARCH_HISI) += hisilicon/ |
@@ -62,7 +64,7 @@ obj-$(CONFIG_MACH_PIC32) += microchip/ | |||
62 | ifeq ($(CONFIG_COMMON_CLK), y) | 64 | ifeq ($(CONFIG_COMMON_CLK), y) |
63 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 65 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
64 | endif | 66 | endif |
65 | obj-$(CONFIG_PLAT_ORION) += mvebu/ | 67 | obj-y += mvebu/ |
66 | obj-$(CONFIG_ARCH_MESON) += meson/ | 68 | obj-$(CONFIG_ARCH_MESON) += meson/ |
67 | obj-$(CONFIG_ARCH_MXS) += mxs/ | 69 | obj-$(CONFIG_ARCH_MXS) += mxs/ |
68 | obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ | 70 | obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ |
@@ -85,3 +87,4 @@ obj-$(CONFIG_X86) += x86/ | |||
85 | obj-$(CONFIG_ARCH_ZX) += zte/ | 87 | obj-$(CONFIG_ARCH_ZX) += zte/ |
86 | obj-$(CONFIG_ARCH_ZYNQ) += zynq/ | 88 | obj-$(CONFIG_ARCH_ZYNQ) += zynq/ |
87 | obj-$(CONFIG_H8300) += h8300/ | 89 | obj-$(CONFIG_H8300) += h8300/ |
90 | obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/ | ||
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 819f5842fa66..8e20c8a76db7 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c | |||
@@ -114,7 +114,7 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) | |||
114 | h32mxclk->regmap = regmap; | 114 | h32mxclk->regmap = regmap; |
115 | 115 | ||
116 | clk = clk_register(NULL, &h32mxclk->hw); | 116 | clk = clk_register(NULL, &h32mxclk->hw); |
117 | if (!clk) { | 117 | if (IS_ERR(clk)) { |
118 | kfree(h32mxclk); | 118 | kfree(h32mxclk); |
119 | return; | 119 | return; |
120 | } | 120 | } |
diff --git a/drivers/clk/axis/Makefile b/drivers/clk/axis/Makefile new file mode 100644 index 000000000000..628c9d3b9a02 --- /dev/null +++ b/drivers/clk/axis/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_MACH_ARTPEC6) += clk-artpec6.o | |||
diff --git a/drivers/clk/axis/clk-artpec6.c b/drivers/clk/axis/clk-artpec6.c new file mode 100644 index 000000000000..ffc988b098e4 --- /dev/null +++ b/drivers/clk/axis/clk-artpec6.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * ARTPEC-6 clock initialization | ||
3 | * | ||
4 | * Copyright 2015-2016 Axis Comunications AB. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk-provider.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <dt-bindings/clock/axis,artpec6-clkctrl.h> | ||
19 | |||
20 | #define NUM_I2S_CLOCKS 2 | ||
21 | |||
22 | struct artpec6_clkctrl_drvdata { | ||
23 | struct clk *clk_table[ARTPEC6_CLK_NUMCLOCKS]; | ||
24 | void __iomem *syscon_base; | ||
25 | struct clk_onecell_data clk_data; | ||
26 | spinlock_t i2scfg_lock; | ||
27 | }; | ||
28 | |||
29 | static struct artpec6_clkctrl_drvdata *clkdata; | ||
30 | |||
31 | static const char *const i2s_clk_names[NUM_I2S_CLOCKS] = { | ||
32 | "i2s0", | ||
33 | "i2s1", | ||
34 | }; | ||
35 | |||
36 | static const int i2s_clk_indexes[NUM_I2S_CLOCKS] = { | ||
37 | ARTPEC6_CLK_I2S0_CLK, | ||
38 | ARTPEC6_CLK_I2S1_CLK, | ||
39 | }; | ||
40 | |||
41 | static void of_artpec6_clkctrl_setup(struct device_node *np) | ||
42 | { | ||
43 | int i; | ||
44 | const char *sys_refclk_name; | ||
45 | u32 pll_mode, pll_m, pll_n; | ||
46 | struct clk **clks; | ||
47 | |||
48 | /* Mandatory parent clock. */ | ||
49 | i = of_property_match_string(np, "clock-names", "sys_refclk"); | ||
50 | if (i < 0) | ||
51 | return; | ||
52 | |||
53 | sys_refclk_name = of_clk_get_parent_name(np, i); | ||
54 | |||
55 | clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL); | ||
56 | if (!clkdata) | ||
57 | return; | ||
58 | |||
59 | clks = clkdata->clk_table; | ||
60 | |||
61 | for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) | ||
62 | clks[i] = ERR_PTR(-EPROBE_DEFER); | ||
63 | |||
64 | clkdata->syscon_base = of_iomap(np, 0); | ||
65 | BUG_ON(clkdata->syscon_base == NULL); | ||
66 | |||
67 | /* Read PLL1 factors configured by boot strap pins. */ | ||
68 | pll_mode = (readl(clkdata->syscon_base) >> 6) & 3; | ||
69 | switch (pll_mode) { | ||
70 | case 0: /* DDR3-2133 mode */ | ||
71 | pll_m = 4; | ||
72 | pll_n = 85; | ||
73 | break; | ||
74 | case 1: /* DDR3-1866 mode */ | ||
75 | pll_m = 6; | ||
76 | pll_n = 112; | ||
77 | break; | ||
78 | case 2: /* DDR3-1600 mode */ | ||
79 | pll_m = 4; | ||
80 | pll_n = 64; | ||
81 | break; | ||
82 | case 3: /* DDR3-1333 mode */ | ||
83 | pll_m = 8; | ||
84 | pll_n = 106; | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | clks[ARTPEC6_CLK_CPU] = | ||
89 | clk_register_fixed_factor(NULL, "cpu", sys_refclk_name, 0, pll_n, | ||
90 | pll_m); | ||
91 | clks[ARTPEC6_CLK_CPU_PERIPH] = | ||
92 | clk_register_fixed_factor(NULL, "cpu_periph", "cpu", 0, 1, 2); | ||
93 | |||
94 | /* EPROBE_DEFER on the apb_clock is not handled in amba devices. */ | ||
95 | clks[ARTPEC6_CLK_UART_PCLK] = | ||
96 | clk_register_fixed_factor(NULL, "uart_pclk", "cpu", 0, 1, 8); | ||
97 | clks[ARTPEC6_CLK_UART_REFCLK] = | ||
98 | clk_register_fixed_rate(NULL, "uart_ref", sys_refclk_name, 0, | ||
99 | 50000000); | ||
100 | |||
101 | clks[ARTPEC6_CLK_SPI_PCLK] = | ||
102 | clk_register_fixed_factor(NULL, "spi_pclk", "cpu", 0, 1, 8); | ||
103 | clks[ARTPEC6_CLK_SPI_SSPCLK] = | ||
104 | clk_register_fixed_rate(NULL, "spi_sspclk", sys_refclk_name, 0, | ||
105 | 50000000); | ||
106 | |||
107 | clks[ARTPEC6_CLK_DBG_PCLK] = | ||
108 | clk_register_fixed_factor(NULL, "dbg_pclk", "cpu", 0, 1, 8); | ||
109 | |||
110 | clkdata->clk_data.clks = clkdata->clk_table; | ||
111 | clkdata->clk_data.clk_num = ARTPEC6_CLK_NUMCLOCKS; | ||
112 | |||
113 | of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data); | ||
114 | } | ||
115 | |||
116 | CLK_OF_DECLARE(artpec6_clkctrl, "axis,artpec6-clkctrl", | ||
117 | of_artpec6_clkctrl_setup); | ||
118 | |||
119 | static int artpec6_clkctrl_probe(struct platform_device *pdev) | ||
120 | { | ||
121 | int propidx; | ||
122 | struct device_node *np = pdev->dev.of_node; | ||
123 | struct device *dev = &pdev->dev; | ||
124 | struct clk **clks = clkdata->clk_table; | ||
125 | const char *sys_refclk_name; | ||
126 | const char *i2s_refclk_name = NULL; | ||
127 | const char *frac_clk_name[2] = { NULL, NULL }; | ||
128 | const char *i2s_mux_parents[2]; | ||
129 | u32 muxreg; | ||
130 | int i; | ||
131 | int err = 0; | ||
132 | |||
133 | /* Mandatory parent clock. */ | ||
134 | propidx = of_property_match_string(np, "clock-names", "sys_refclk"); | ||
135 | if (propidx < 0) | ||
136 | return -EINVAL; | ||
137 | |||
138 | sys_refclk_name = of_clk_get_parent_name(np, propidx); | ||
139 | |||
140 | /* Find clock names of optional parent clocks. */ | ||
141 | propidx = of_property_match_string(np, "clock-names", "i2s_refclk"); | ||
142 | if (propidx >= 0) | ||
143 | i2s_refclk_name = of_clk_get_parent_name(np, propidx); | ||
144 | |||
145 | propidx = of_property_match_string(np, "clock-names", "frac_clk0"); | ||
146 | if (propidx >= 0) | ||
147 | frac_clk_name[0] = of_clk_get_parent_name(np, propidx); | ||
148 | propidx = of_property_match_string(np, "clock-names", "frac_clk1"); | ||
149 | if (propidx >= 0) | ||
150 | frac_clk_name[1] = of_clk_get_parent_name(np, propidx); | ||
151 | |||
152 | spin_lock_init(&clkdata->i2scfg_lock); | ||
153 | |||
154 | clks[ARTPEC6_CLK_NAND_CLKA] = | ||
155 | clk_register_fixed_factor(dev, "nand_clka", "cpu", 0, 1, 8); | ||
156 | clks[ARTPEC6_CLK_NAND_CLKB] = | ||
157 | clk_register_fixed_rate(dev, "nand_clkb", sys_refclk_name, 0, | ||
158 | 100000000); | ||
159 | clks[ARTPEC6_CLK_ETH_ACLK] = | ||
160 | clk_register_fixed_factor(dev, "eth_aclk", "cpu", 0, 1, 4); | ||
161 | clks[ARTPEC6_CLK_DMA_ACLK] = | ||
162 | clk_register_fixed_factor(dev, "dma_aclk", "cpu", 0, 1, 4); | ||
163 | clks[ARTPEC6_CLK_PTP_REF] = | ||
164 | clk_register_fixed_rate(dev, "ptp_ref", sys_refclk_name, 0, | ||
165 | 100000000); | ||
166 | clks[ARTPEC6_CLK_SD_PCLK] = | ||
167 | clk_register_fixed_rate(dev, "sd_pclk", sys_refclk_name, 0, | ||
168 | 100000000); | ||
169 | clks[ARTPEC6_CLK_SD_IMCLK] = | ||
170 | clk_register_fixed_rate(dev, "sd_imclk", sys_refclk_name, 0, | ||
171 | 100000000); | ||
172 | clks[ARTPEC6_CLK_I2S_HST] = | ||
173 | clk_register_fixed_factor(dev, "i2s_hst", "cpu", 0, 1, 8); | ||
174 | |||
175 | for (i = 0; i < NUM_I2S_CLOCKS; ++i) { | ||
176 | if (i2s_refclk_name && frac_clk_name[i]) { | ||
177 | i2s_mux_parents[0] = frac_clk_name[i]; | ||
178 | i2s_mux_parents[1] = i2s_refclk_name; | ||
179 | |||
180 | clks[i2s_clk_indexes[i]] = | ||
181 | clk_register_mux(dev, i2s_clk_names[i], | ||
182 | i2s_mux_parents, 2, | ||
183 | CLK_SET_RATE_NO_REPARENT | | ||
184 | CLK_SET_RATE_PARENT, | ||
185 | clkdata->syscon_base + 0x14, i, 1, | ||
186 | 0, &clkdata->i2scfg_lock); | ||
187 | } else if (frac_clk_name[i]) { | ||
188 | /* Lock the mux for internal clock reference. */ | ||
189 | muxreg = readl(clkdata->syscon_base + 0x14); | ||
190 | muxreg &= ~BIT(i); | ||
191 | writel(muxreg, clkdata->syscon_base + 0x14); | ||
192 | clks[i2s_clk_indexes[i]] = | ||
193 | clk_register_fixed_factor(dev, i2s_clk_names[i], | ||
194 | frac_clk_name[i], 0, 1, | ||
195 | 1); | ||
196 | } else if (i2s_refclk_name) { | ||
197 | /* Lock the mux for external clock reference. */ | ||
198 | muxreg = readl(clkdata->syscon_base + 0x14); | ||
199 | muxreg |= BIT(i); | ||
200 | writel(muxreg, clkdata->syscon_base + 0x14); | ||
201 | clks[i2s_clk_indexes[i]] = | ||
202 | clk_register_fixed_factor(dev, i2s_clk_names[i], | ||
203 | i2s_refclk_name, 0, 1, 1); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | clks[ARTPEC6_CLK_I2C] = | ||
208 | clk_register_fixed_rate(dev, "i2c", sys_refclk_name, 0, 100000000); | ||
209 | |||
210 | clks[ARTPEC6_CLK_SYS_TIMER] = | ||
211 | clk_register_fixed_rate(dev, "timer", sys_refclk_name, 0, | ||
212 | 100000000); | ||
213 | clks[ARTPEC6_CLK_FRACDIV_IN] = | ||
214 | clk_register_fixed_rate(dev, "fracdiv_in", sys_refclk_name, 0, | ||
215 | 600000000); | ||
216 | |||
217 | for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) { | ||
218 | if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER) { | ||
219 | dev_err(dev, | ||
220 | "Failed to register clock at index %d err=%ld\n", | ||
221 | i, PTR_ERR(clks[i])); | ||
222 | err = PTR_ERR(clks[i]); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | return err; | ||
227 | } | ||
228 | |||
229 | static const struct of_device_id artpec_clkctrl_of_match[] = { | ||
230 | { .compatible = "axis,artpec6-clkctrl" }, | ||
231 | {} | ||
232 | }; | ||
233 | |||
234 | static struct platform_driver artpec6_clkctrl_driver = { | ||
235 | .probe = artpec6_clkctrl_probe, | ||
236 | .driver = { | ||
237 | .name = "artpec6_clkctrl", | ||
238 | .of_match_table = artpec_clkctrl_of_match, | ||
239 | }, | ||
240 | }; | ||
241 | |||
242 | builtin_platform_driver(artpec6_clkctrl_driver); | ||
diff --git a/drivers/clk/axs10x/Makefile b/drivers/clk/axs10x/Makefile new file mode 100644 index 000000000000..01996b871b06 --- /dev/null +++ b/drivers/clk/axs10x/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += i2s_pll_clock.o | |||
diff --git a/drivers/clk/axs10x/i2s_pll_clock.c b/drivers/clk/axs10x/i2s_pll_clock.c new file mode 100644 index 000000000000..411310d29581 --- /dev/null +++ b/drivers/clk/axs10x/i2s_pll_clock.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Synopsys AXS10X SDP I2S PLL clock driver | ||
3 | * | ||
4 | * Copyright (C) 2016 Synopsys | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/of.h> | ||
19 | |||
20 | /* PLL registers addresses */ | ||
21 | #define PLL_IDIV_REG 0x0 | ||
22 | #define PLL_FBDIV_REG 0x4 | ||
23 | #define PLL_ODIV0_REG 0x8 | ||
24 | #define PLL_ODIV1_REG 0xC | ||
25 | |||
26 | struct i2s_pll_cfg { | ||
27 | unsigned int rate; | ||
28 | unsigned int idiv; | ||
29 | unsigned int fbdiv; | ||
30 | unsigned int odiv0; | ||
31 | unsigned int odiv1; | ||
32 | }; | ||
33 | |||
34 | static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = { | ||
35 | /* 27 Mhz */ | ||
36 | { 1024000, 0x104, 0x451, 0x10E38, 0x2000 }, | ||
37 | { 1411200, 0x104, 0x596, 0x10D35, 0x2000 }, | ||
38 | { 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 }, | ||
39 | { 2048000, 0x82, 0x451, 0x10E38, 0x2000 }, | ||
40 | { 2822400, 0x82, 0x596, 0x10D35, 0x2000 }, | ||
41 | { 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 }, | ||
42 | { 2116800, 0x82, 0x3CF, 0x10C30, 0x2000 }, | ||
43 | { 2304000, 0x104, 0x79E, 0x10B2C, 0x2000 }, | ||
44 | { 0, 0, 0, 0, 0 }, | ||
45 | }; | ||
46 | |||
47 | static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = { | ||
48 | /* 28.224 Mhz */ | ||
49 | { 1024000, 0x82, 0x105, 0x107DF, 0x2000 }, | ||
50 | { 1411200, 0x28A, 0x1, 0x10001, 0x2000 }, | ||
51 | { 1536000, 0xA28, 0x187, 0x10042, 0x2000 }, | ||
52 | { 2048000, 0x41, 0x105, 0x107DF, 0x2000 }, | ||
53 | { 2822400, 0x145, 0x1, 0x10001, 0x2000 }, | ||
54 | { 3072000, 0x514, 0x187, 0x10042, 0x2000 }, | ||
55 | { 2116800, 0x514, 0x42, 0x10001, 0x2000 }, | ||
56 | { 2304000, 0x619, 0x82, 0x10001, 0x2000 }, | ||
57 | { 0, 0, 0, 0, 0 }, | ||
58 | }; | ||
59 | |||
60 | struct i2s_pll_clk { | ||
61 | void __iomem *base; | ||
62 | struct clk_hw hw; | ||
63 | struct device *dev; | ||
64 | }; | ||
65 | |||
66 | static inline void i2s_pll_write(struct i2s_pll_clk *clk, unsigned int reg, | ||
67 | unsigned int val) | ||
68 | { | ||
69 | writel_relaxed(val, clk->base + reg); | ||
70 | } | ||
71 | |||
72 | static inline unsigned int i2s_pll_read(struct i2s_pll_clk *clk, | ||
73 | unsigned int reg) | ||
74 | { | ||
75 | return readl_relaxed(clk->base + reg); | ||
76 | } | ||
77 | |||
78 | static inline struct i2s_pll_clk *to_i2s_pll_clk(struct clk_hw *hw) | ||
79 | { | ||
80 | return container_of(hw, struct i2s_pll_clk, hw); | ||
81 | } | ||
82 | |||
83 | static inline unsigned int i2s_pll_get_value(unsigned int val) | ||
84 | { | ||
85 | return (val & 0x3F) + ((val >> 6) & 0x3F); | ||
86 | } | ||
87 | |||
88 | static const struct i2s_pll_cfg *i2s_pll_get_cfg(unsigned long prate) | ||
89 | { | ||
90 | switch (prate) { | ||
91 | case 27000000: | ||
92 | return i2s_pll_cfg_27m; | ||
93 | case 28224000: | ||
94 | return i2s_pll_cfg_28m; | ||
95 | default: | ||
96 | return NULL; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw, | ||
101 | unsigned long parent_rate) | ||
102 | { | ||
103 | struct i2s_pll_clk *clk = to_i2s_pll_clk(hw); | ||
104 | unsigned int idiv, fbdiv, odiv; | ||
105 | |||
106 | idiv = i2s_pll_get_value(i2s_pll_read(clk, PLL_IDIV_REG)); | ||
107 | fbdiv = i2s_pll_get_value(i2s_pll_read(clk, PLL_FBDIV_REG)); | ||
108 | odiv = i2s_pll_get_value(i2s_pll_read(clk, PLL_ODIV0_REG)); | ||
109 | |||
110 | return ((parent_rate / idiv) * fbdiv) / odiv; | ||
111 | } | ||
112 | |||
113 | static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate, | ||
114 | unsigned long *prate) | ||
115 | { | ||
116 | struct i2s_pll_clk *clk = to_i2s_pll_clk(hw); | ||
117 | const struct i2s_pll_cfg *pll_cfg = i2s_pll_get_cfg(*prate); | ||
118 | int i; | ||
119 | |||
120 | if (!pll_cfg) { | ||
121 | dev_err(clk->dev, "invalid parent rate=%ld\n", *prate); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | |||
125 | for (i = 0; pll_cfg[i].rate != 0; i++) | ||
126 | if (pll_cfg[i].rate == rate) | ||
127 | return rate; | ||
128 | |||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate, | ||
133 | unsigned long parent_rate) | ||
134 | { | ||
135 | struct i2s_pll_clk *clk = to_i2s_pll_clk(hw); | ||
136 | const struct i2s_pll_cfg *pll_cfg = i2s_pll_get_cfg(parent_rate); | ||
137 | int i; | ||
138 | |||
139 | if (!pll_cfg) { | ||
140 | dev_err(clk->dev, "invalid parent rate=%ld\n", parent_rate); | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | for (i = 0; pll_cfg[i].rate != 0; i++) { | ||
145 | if (pll_cfg[i].rate == rate) { | ||
146 | i2s_pll_write(clk, PLL_IDIV_REG, pll_cfg[i].idiv); | ||
147 | i2s_pll_write(clk, PLL_FBDIV_REG, pll_cfg[i].fbdiv); | ||
148 | i2s_pll_write(clk, PLL_ODIV0_REG, pll_cfg[i].odiv0); | ||
149 | i2s_pll_write(clk, PLL_ODIV1_REG, pll_cfg[i].odiv1); | ||
150 | return 0; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate, | ||
155 | parent_rate); | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | static const struct clk_ops i2s_pll_ops = { | ||
160 | .recalc_rate = i2s_pll_recalc_rate, | ||
161 | .round_rate = i2s_pll_round_rate, | ||
162 | .set_rate = i2s_pll_set_rate, | ||
163 | }; | ||
164 | |||
165 | static int i2s_pll_clk_probe(struct platform_device *pdev) | ||
166 | { | ||
167 | struct device *dev = &pdev->dev; | ||
168 | struct device_node *node = dev->of_node; | ||
169 | const char *clk_name; | ||
170 | const char *parent_name; | ||
171 | struct clk *clk; | ||
172 | struct i2s_pll_clk *pll_clk; | ||
173 | struct clk_init_data init; | ||
174 | struct resource *mem; | ||
175 | |||
176 | pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); | ||
177 | if (!pll_clk) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
181 | pll_clk->base = devm_ioremap_resource(dev, mem); | ||
182 | if (IS_ERR(pll_clk->base)) | ||
183 | return PTR_ERR(pll_clk->base); | ||
184 | |||
185 | clk_name = node->name; | ||
186 | init.name = clk_name; | ||
187 | init.ops = &i2s_pll_ops; | ||
188 | parent_name = of_clk_get_parent_name(node, 0); | ||
189 | init.parent_names = &parent_name; | ||
190 | init.num_parents = 1; | ||
191 | pll_clk->hw.init = &init; | ||
192 | pll_clk->dev = dev; | ||
193 | |||
194 | clk = devm_clk_register(dev, &pll_clk->hw); | ||
195 | if (IS_ERR(clk)) { | ||
196 | dev_err(dev, "failed to register %s clock (%ld)\n", | ||
197 | clk_name, PTR_ERR(clk)); | ||
198 | return PTR_ERR(clk); | ||
199 | } | ||
200 | |||
201 | return of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
202 | } | ||
203 | |||
204 | static int i2s_pll_clk_remove(struct platform_device *pdev) | ||
205 | { | ||
206 | of_clk_del_provider(pdev->dev.of_node); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static const struct of_device_id i2s_pll_clk_id[] = { | ||
211 | { .compatible = "snps,axs10x-i2s-pll-clock", }, | ||
212 | { }, | ||
213 | }; | ||
214 | MODULE_DEVICE_TABLE(of, i2s_pll_clk_id); | ||
215 | |||
216 | static struct platform_driver i2s_pll_clk_driver = { | ||
217 | .driver = { | ||
218 | .name = "axs10x-i2s-pll-clock", | ||
219 | .of_match_table = i2s_pll_clk_id, | ||
220 | }, | ||
221 | .probe = i2s_pll_clk_probe, | ||
222 | .remove = i2s_pll_clk_remove, | ||
223 | }; | ||
224 | module_platform_driver(i2s_pll_clk_driver); | ||
225 | |||
226 | MODULE_AUTHOR("Jose Abreu <joabreu@synopsys.com>"); | ||
227 | MODULE_DESCRIPTION("Synopsys AXS10X SDP I2S PLL Clock Driver"); | ||
228 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index c74ed3fd496d..7a7970865c2d 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c | |||
@@ -12,9 +12,6 @@ | |||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | 15 | */ |
19 | 16 | ||
20 | /** | 17 | /** |
@@ -40,6 +37,7 @@ | |||
40 | #include <linux/clk-provider.h> | 37 | #include <linux/clk-provider.h> |
41 | #include <linux/clkdev.h> | 38 | #include <linux/clkdev.h> |
42 | #include <linux/clk/bcm2835.h> | 39 | #include <linux/clk/bcm2835.h> |
40 | #include <linux/debugfs.h> | ||
43 | #include <linux/module.h> | 41 | #include <linux/module.h> |
44 | #include <linux/of.h> | 42 | #include <linux/of.h> |
45 | #include <linux/platform_device.h> | 43 | #include <linux/platform_device.h> |
@@ -51,6 +49,7 @@ | |||
51 | #define CM_GNRICCTL 0x000 | 49 | #define CM_GNRICCTL 0x000 |
52 | #define CM_GNRICDIV 0x004 | 50 | #define CM_GNRICDIV 0x004 |
53 | # define CM_DIV_FRAC_BITS 12 | 51 | # define CM_DIV_FRAC_BITS 12 |
52 | # define CM_DIV_FRAC_MASK GENMASK(CM_DIV_FRAC_BITS - 1, 0) | ||
54 | 53 | ||
55 | #define CM_VPUCTL 0x008 | 54 | #define CM_VPUCTL 0x008 |
56 | #define CM_VPUDIV 0x00c | 55 | #define CM_VPUDIV 0x00c |
@@ -118,6 +117,8 @@ | |||
118 | #define CM_SDCCTL 0x1a8 | 117 | #define CM_SDCCTL 0x1a8 |
119 | #define CM_SDCDIV 0x1ac | 118 | #define CM_SDCDIV 0x1ac |
120 | #define CM_ARMCTL 0x1b0 | 119 | #define CM_ARMCTL 0x1b0 |
120 | #define CM_AVEOCTL 0x1b8 | ||
121 | #define CM_AVEODIV 0x1bc | ||
121 | #define CM_EMMCCTL 0x1c0 | 122 | #define CM_EMMCCTL 0x1c0 |
122 | #define CM_EMMCDIV 0x1c4 | 123 | #define CM_EMMCDIV 0x1c4 |
123 | 124 | ||
@@ -128,6 +129,7 @@ | |||
128 | # define CM_GATE BIT(CM_GATE_BIT) | 129 | # define CM_GATE BIT(CM_GATE_BIT) |
129 | # define CM_BUSY BIT(7) | 130 | # define CM_BUSY BIT(7) |
130 | # define CM_BUSYD BIT(8) | 131 | # define CM_BUSYD BIT(8) |
132 | # define CM_FRAC BIT(9) | ||
131 | # define CM_SRC_SHIFT 0 | 133 | # define CM_SRC_SHIFT 0 |
132 | # define CM_SRC_BITS 4 | 134 | # define CM_SRC_BITS 4 |
133 | # define CM_SRC_MASK 0xf | 135 | # define CM_SRC_MASK 0xf |
@@ -297,11 +299,11 @@ | |||
297 | struct bcm2835_cprman { | 299 | struct bcm2835_cprman { |
298 | struct device *dev; | 300 | struct device *dev; |
299 | void __iomem *regs; | 301 | void __iomem *regs; |
300 | spinlock_t regs_lock; | 302 | spinlock_t regs_lock; /* spinlock for all clocks */ |
301 | const char *osc_name; | 303 | const char *osc_name; |
302 | 304 | ||
303 | struct clk_onecell_data onecell; | 305 | struct clk_onecell_data onecell; |
304 | struct clk *clks[BCM2835_CLOCK_COUNT]; | 306 | struct clk *clks[]; |
305 | }; | 307 | }; |
306 | 308 | ||
307 | static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val) | 309 | static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val) |
@@ -314,6 +316,27 @@ static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg) | |||
314 | return readl(cprman->regs + reg); | 316 | return readl(cprman->regs + reg); |
315 | } | 317 | } |
316 | 318 | ||
319 | static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base, | ||
320 | struct debugfs_reg32 *regs, size_t nregs, | ||
321 | struct dentry *dentry) | ||
322 | { | ||
323 | struct dentry *regdump; | ||
324 | struct debugfs_regset32 *regset; | ||
325 | |||
326 | regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL); | ||
327 | if (!regset) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | regset->regs = regs; | ||
331 | regset->nregs = nregs; | ||
332 | regset->base = cprman->regs + base; | ||
333 | |||
334 | regdump = debugfs_create_regset32("regdump", S_IRUGO, dentry, | ||
335 | regset); | ||
336 | |||
337 | return regdump ? 0 : -ENOMEM; | ||
338 | } | ||
339 | |||
317 | /* | 340 | /* |
318 | * These are fixed clocks. They're probably not all root clocks and it may | 341 | * These are fixed clocks. They're probably not all root clocks and it may |
319 | * be possible to turn them on and off but until this is mapped out better | 342 | * be possible to turn them on and off but until this is mapped out better |
@@ -377,132 +400,27 @@ struct bcm2835_pll_ana_bits { | |||
377 | static const struct bcm2835_pll_ana_bits bcm2835_ana_default = { | 400 | static const struct bcm2835_pll_ana_bits bcm2835_ana_default = { |
378 | .mask0 = 0, | 401 | .mask0 = 0, |
379 | .set0 = 0, | 402 | .set0 = 0, |
380 | .mask1 = ~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK), | 403 | .mask1 = (u32)~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK), |
381 | .set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT), | 404 | .set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT), |
382 | .mask3 = ~A2W_PLL_KA_MASK, | 405 | .mask3 = (u32)~A2W_PLL_KA_MASK, |
383 | .set3 = (2 << A2W_PLL_KA_SHIFT), | 406 | .set3 = (2 << A2W_PLL_KA_SHIFT), |
384 | .fb_prediv_mask = BIT(14), | 407 | .fb_prediv_mask = BIT(14), |
385 | }; | 408 | }; |
386 | 409 | ||
387 | static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = { | 410 | static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = { |
388 | .mask0 = ~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK), | 411 | .mask0 = (u32)~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK), |
389 | .set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT), | 412 | .set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT), |
390 | .mask1 = ~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK), | 413 | .mask1 = (u32)~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK), |
391 | .set1 = (6 << A2W_PLLH_KP_SHIFT), | 414 | .set1 = (6 << A2W_PLLH_KP_SHIFT), |
392 | .mask3 = 0, | 415 | .mask3 = 0, |
393 | .set3 = 0, | 416 | .set3 = 0, |
394 | .fb_prediv_mask = BIT(11), | 417 | .fb_prediv_mask = BIT(11), |
395 | }; | 418 | }; |
396 | 419 | ||
397 | /* | ||
398 | * PLLA is the auxiliary PLL, used to drive the CCP2 (Compact Camera | ||
399 | * Port 2) transmitter clock. | ||
400 | * | ||
401 | * It is in the PX LDO power domain, which is on when the AUDIO domain | ||
402 | * is on. | ||
403 | */ | ||
404 | static const struct bcm2835_pll_data bcm2835_plla_data = { | ||
405 | .name = "plla", | ||
406 | .cm_ctrl_reg = CM_PLLA, | ||
407 | .a2w_ctrl_reg = A2W_PLLA_CTRL, | ||
408 | .frac_reg = A2W_PLLA_FRAC, | ||
409 | .ana_reg_base = A2W_PLLA_ANA0, | ||
410 | .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE, | ||
411 | .lock_mask = CM_LOCK_FLOCKA, | ||
412 | |||
413 | .ana = &bcm2835_ana_default, | ||
414 | |||
415 | .min_rate = 600000000u, | ||
416 | .max_rate = 2400000000u, | ||
417 | .max_fb_rate = BCM2835_MAX_FB_RATE, | ||
418 | }; | ||
419 | |||
420 | /* PLLB is used for the ARM's clock. */ | ||
421 | static const struct bcm2835_pll_data bcm2835_pllb_data = { | ||
422 | .name = "pllb", | ||
423 | .cm_ctrl_reg = CM_PLLB, | ||
424 | .a2w_ctrl_reg = A2W_PLLB_CTRL, | ||
425 | .frac_reg = A2W_PLLB_FRAC, | ||
426 | .ana_reg_base = A2W_PLLB_ANA0, | ||
427 | .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE, | ||
428 | .lock_mask = CM_LOCK_FLOCKB, | ||
429 | |||
430 | .ana = &bcm2835_ana_default, | ||
431 | |||
432 | .min_rate = 600000000u, | ||
433 | .max_rate = 3000000000u, | ||
434 | .max_fb_rate = BCM2835_MAX_FB_RATE, | ||
435 | }; | ||
436 | |||
437 | /* | ||
438 | * PLLC is the core PLL, used to drive the core VPU clock. | ||
439 | * | ||
440 | * It is in the PX LDO power domain, which is on when the AUDIO domain | ||
441 | * is on. | ||
442 | */ | ||
443 | static const struct bcm2835_pll_data bcm2835_pllc_data = { | ||
444 | .name = "pllc", | ||
445 | .cm_ctrl_reg = CM_PLLC, | ||
446 | .a2w_ctrl_reg = A2W_PLLC_CTRL, | ||
447 | .frac_reg = A2W_PLLC_FRAC, | ||
448 | .ana_reg_base = A2W_PLLC_ANA0, | ||
449 | .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, | ||
450 | .lock_mask = CM_LOCK_FLOCKC, | ||
451 | |||
452 | .ana = &bcm2835_ana_default, | ||
453 | |||
454 | .min_rate = 600000000u, | ||
455 | .max_rate = 3000000000u, | ||
456 | .max_fb_rate = BCM2835_MAX_FB_RATE, | ||
457 | }; | ||
458 | |||
459 | /* | ||
460 | * PLLD is the display PLL, used to drive DSI display panels. | ||
461 | * | ||
462 | * It is in the PX LDO power domain, which is on when the AUDIO domain | ||
463 | * is on. | ||
464 | */ | ||
465 | static const struct bcm2835_pll_data bcm2835_plld_data = { | ||
466 | .name = "plld", | ||
467 | .cm_ctrl_reg = CM_PLLD, | ||
468 | .a2w_ctrl_reg = A2W_PLLD_CTRL, | ||
469 | .frac_reg = A2W_PLLD_FRAC, | ||
470 | .ana_reg_base = A2W_PLLD_ANA0, | ||
471 | .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE, | ||
472 | .lock_mask = CM_LOCK_FLOCKD, | ||
473 | |||
474 | .ana = &bcm2835_ana_default, | ||
475 | |||
476 | .min_rate = 600000000u, | ||
477 | .max_rate = 2400000000u, | ||
478 | .max_fb_rate = BCM2835_MAX_FB_RATE, | ||
479 | }; | ||
480 | |||
481 | /* | ||
482 | * PLLH is used to supply the pixel clock or the AUX clock for the TV | ||
483 | * encoder. | ||
484 | * | ||
485 | * It is in the HDMI power domain. | ||
486 | */ | ||
487 | static const struct bcm2835_pll_data bcm2835_pllh_data = { | ||
488 | "pllh", | ||
489 | .cm_ctrl_reg = CM_PLLH, | ||
490 | .a2w_ctrl_reg = A2W_PLLH_CTRL, | ||
491 | .frac_reg = A2W_PLLH_FRAC, | ||
492 | .ana_reg_base = A2W_PLLH_ANA0, | ||
493 | .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, | ||
494 | .lock_mask = CM_LOCK_FLOCKH, | ||
495 | |||
496 | .ana = &bcm2835_ana_pllh, | ||
497 | |||
498 | .min_rate = 600000000u, | ||
499 | .max_rate = 3000000000u, | ||
500 | .max_fb_rate = BCM2835_MAX_FB_RATE, | ||
501 | }; | ||
502 | |||
503 | struct bcm2835_pll_divider_data { | 420 | struct bcm2835_pll_divider_data { |
504 | const char *name; | 421 | const char *name; |
505 | const struct bcm2835_pll_data *source_pll; | 422 | const char *source_pll; |
423 | |||
506 | u32 cm_reg; | 424 | u32 cm_reg; |
507 | u32 a2w_reg; | 425 | u32 a2w_reg; |
508 | 426 | ||
@@ -511,124 +429,6 @@ struct bcm2835_pll_divider_data { | |||
511 | u32 fixed_divider; | 429 | u32 fixed_divider; |
512 | }; | 430 | }; |
513 | 431 | ||
514 | static const struct bcm2835_pll_divider_data bcm2835_plla_core_data = { | ||
515 | .name = "plla_core", | ||
516 | .source_pll = &bcm2835_plla_data, | ||
517 | .cm_reg = CM_PLLA, | ||
518 | .a2w_reg = A2W_PLLA_CORE, | ||
519 | .load_mask = CM_PLLA_LOADCORE, | ||
520 | .hold_mask = CM_PLLA_HOLDCORE, | ||
521 | .fixed_divider = 1, | ||
522 | }; | ||
523 | |||
524 | static const struct bcm2835_pll_divider_data bcm2835_plla_per_data = { | ||
525 | .name = "plla_per", | ||
526 | .source_pll = &bcm2835_plla_data, | ||
527 | .cm_reg = CM_PLLA, | ||
528 | .a2w_reg = A2W_PLLA_PER, | ||
529 | .load_mask = CM_PLLA_LOADPER, | ||
530 | .hold_mask = CM_PLLA_HOLDPER, | ||
531 | .fixed_divider = 1, | ||
532 | }; | ||
533 | |||
534 | static const struct bcm2835_pll_divider_data bcm2835_pllb_arm_data = { | ||
535 | .name = "pllb_arm", | ||
536 | .source_pll = &bcm2835_pllb_data, | ||
537 | .cm_reg = CM_PLLB, | ||
538 | .a2w_reg = A2W_PLLB_ARM, | ||
539 | .load_mask = CM_PLLB_LOADARM, | ||
540 | .hold_mask = CM_PLLB_HOLDARM, | ||
541 | .fixed_divider = 1, | ||
542 | }; | ||
543 | |||
544 | static const struct bcm2835_pll_divider_data bcm2835_pllc_core0_data = { | ||
545 | .name = "pllc_core0", | ||
546 | .source_pll = &bcm2835_pllc_data, | ||
547 | .cm_reg = CM_PLLC, | ||
548 | .a2w_reg = A2W_PLLC_CORE0, | ||
549 | .load_mask = CM_PLLC_LOADCORE0, | ||
550 | .hold_mask = CM_PLLC_HOLDCORE0, | ||
551 | .fixed_divider = 1, | ||
552 | }; | ||
553 | |||
554 | static const struct bcm2835_pll_divider_data bcm2835_pllc_core1_data = { | ||
555 | .name = "pllc_core1", .source_pll = &bcm2835_pllc_data, | ||
556 | .cm_reg = CM_PLLC, A2W_PLLC_CORE1, | ||
557 | .load_mask = CM_PLLC_LOADCORE1, | ||
558 | .hold_mask = CM_PLLC_HOLDCORE1, | ||
559 | .fixed_divider = 1, | ||
560 | }; | ||
561 | |||
562 | static const struct bcm2835_pll_divider_data bcm2835_pllc_core2_data = { | ||
563 | .name = "pllc_core2", | ||
564 | .source_pll = &bcm2835_pllc_data, | ||
565 | .cm_reg = CM_PLLC, | ||
566 | .a2w_reg = A2W_PLLC_CORE2, | ||
567 | .load_mask = CM_PLLC_LOADCORE2, | ||
568 | .hold_mask = CM_PLLC_HOLDCORE2, | ||
569 | .fixed_divider = 1, | ||
570 | }; | ||
571 | |||
572 | static const struct bcm2835_pll_divider_data bcm2835_pllc_per_data = { | ||
573 | .name = "pllc_per", | ||
574 | .source_pll = &bcm2835_pllc_data, | ||
575 | .cm_reg = CM_PLLC, | ||
576 | .a2w_reg = A2W_PLLC_PER, | ||
577 | .load_mask = CM_PLLC_LOADPER, | ||
578 | .hold_mask = CM_PLLC_HOLDPER, | ||
579 | .fixed_divider = 1, | ||
580 | }; | ||
581 | |||
582 | static const struct bcm2835_pll_divider_data bcm2835_plld_core_data = { | ||
583 | .name = "plld_core", | ||
584 | .source_pll = &bcm2835_plld_data, | ||
585 | .cm_reg = CM_PLLD, | ||
586 | .a2w_reg = A2W_PLLD_CORE, | ||
587 | .load_mask = CM_PLLD_LOADCORE, | ||
588 | .hold_mask = CM_PLLD_HOLDCORE, | ||
589 | .fixed_divider = 1, | ||
590 | }; | ||
591 | |||
592 | static const struct bcm2835_pll_divider_data bcm2835_plld_per_data = { | ||
593 | .name = "plld_per", | ||
594 | .source_pll = &bcm2835_plld_data, | ||
595 | .cm_reg = CM_PLLD, | ||
596 | .a2w_reg = A2W_PLLD_PER, | ||
597 | .load_mask = CM_PLLD_LOADPER, | ||
598 | .hold_mask = CM_PLLD_HOLDPER, | ||
599 | .fixed_divider = 1, | ||
600 | }; | ||
601 | |||
602 | static const struct bcm2835_pll_divider_data bcm2835_pllh_rcal_data = { | ||
603 | .name = "pllh_rcal", | ||
604 | .source_pll = &bcm2835_pllh_data, | ||
605 | .cm_reg = CM_PLLH, | ||
606 | .a2w_reg = A2W_PLLH_RCAL, | ||
607 | .load_mask = CM_PLLH_LOADRCAL, | ||
608 | .hold_mask = 0, | ||
609 | .fixed_divider = 10, | ||
610 | }; | ||
611 | |||
612 | static const struct bcm2835_pll_divider_data bcm2835_pllh_aux_data = { | ||
613 | .name = "pllh_aux", | ||
614 | .source_pll = &bcm2835_pllh_data, | ||
615 | .cm_reg = CM_PLLH, | ||
616 | .a2w_reg = A2W_PLLH_AUX, | ||
617 | .load_mask = CM_PLLH_LOADAUX, | ||
618 | .hold_mask = 0, | ||
619 | .fixed_divider = 10, | ||
620 | }; | ||
621 | |||
622 | static const struct bcm2835_pll_divider_data bcm2835_pllh_pix_data = { | ||
623 | .name = "pllh_pix", | ||
624 | .source_pll = &bcm2835_pllh_data, | ||
625 | .cm_reg = CM_PLLH, | ||
626 | .a2w_reg = A2W_PLLH_PIX, | ||
627 | .load_mask = CM_PLLH_LOADPIX, | ||
628 | .hold_mask = 0, | ||
629 | .fixed_divider = 10, | ||
630 | }; | ||
631 | |||
632 | struct bcm2835_clock_data { | 432 | struct bcm2835_clock_data { |
633 | const char *name; | 433 | const char *name; |
634 | 434 | ||
@@ -644,187 +444,14 @@ struct bcm2835_clock_data { | |||
644 | u32 frac_bits; | 444 | u32 frac_bits; |
645 | 445 | ||
646 | bool is_vpu_clock; | 446 | bool is_vpu_clock; |
447 | bool is_mash_clock; | ||
647 | }; | 448 | }; |
648 | 449 | ||
649 | static const char *const bcm2835_clock_per_parents[] = { | 450 | struct bcm2835_gate_data { |
650 | "gnd", | 451 | const char *name; |
651 | "xosc", | 452 | const char *parent; |
652 | "testdebug0", | ||
653 | "testdebug1", | ||
654 | "plla_per", | ||
655 | "pllc_per", | ||
656 | "plld_per", | ||
657 | "pllh_aux", | ||
658 | }; | ||
659 | |||
660 | static const char *const bcm2835_clock_vpu_parents[] = { | ||
661 | "gnd", | ||
662 | "xosc", | ||
663 | "testdebug0", | ||
664 | "testdebug1", | ||
665 | "plla_core", | ||
666 | "pllc_core0", | ||
667 | "plld_core", | ||
668 | "pllh_aux", | ||
669 | "pllc_core1", | ||
670 | "pllc_core2", | ||
671 | }; | ||
672 | |||
673 | static const char *const bcm2835_clock_osc_parents[] = { | ||
674 | "gnd", | ||
675 | "xosc", | ||
676 | "testdebug0", | ||
677 | "testdebug1" | ||
678 | }; | ||
679 | |||
680 | /* | ||
681 | * Used for a 1Mhz clock for the system clocksource, and also used by | ||
682 | * the watchdog timer and the camera pulse generator. | ||
683 | */ | ||
684 | static const struct bcm2835_clock_data bcm2835_clock_timer_data = { | ||
685 | .name = "timer", | ||
686 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), | ||
687 | .parents = bcm2835_clock_osc_parents, | ||
688 | .ctl_reg = CM_TIMERCTL, | ||
689 | .div_reg = CM_TIMERDIV, | ||
690 | .int_bits = 6, | ||
691 | .frac_bits = 12, | ||
692 | }; | ||
693 | |||
694 | /* One Time Programmable Memory clock. Maximum 10Mhz. */ | ||
695 | static const struct bcm2835_clock_data bcm2835_clock_otp_data = { | ||
696 | .name = "otp", | ||
697 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), | ||
698 | .parents = bcm2835_clock_osc_parents, | ||
699 | .ctl_reg = CM_OTPCTL, | ||
700 | .div_reg = CM_OTPDIV, | ||
701 | .int_bits = 4, | ||
702 | .frac_bits = 0, | ||
703 | }; | ||
704 | |||
705 | /* | ||
706 | * VPU clock. This doesn't have an enable bit, since it drives the | ||
707 | * bus for everything else, and is special so it doesn't need to be | ||
708 | * gated for rate changes. It is also known as "clk_audio" in various | ||
709 | * hardware documentation. | ||
710 | */ | ||
711 | static const struct bcm2835_clock_data bcm2835_clock_vpu_data = { | ||
712 | .name = "vpu", | ||
713 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), | ||
714 | .parents = bcm2835_clock_vpu_parents, | ||
715 | .ctl_reg = CM_VPUCTL, | ||
716 | .div_reg = CM_VPUDIV, | ||
717 | .int_bits = 12, | ||
718 | .frac_bits = 8, | ||
719 | .is_vpu_clock = true, | ||
720 | }; | ||
721 | |||
722 | static const struct bcm2835_clock_data bcm2835_clock_v3d_data = { | ||
723 | .name = "v3d", | ||
724 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), | ||
725 | .parents = bcm2835_clock_vpu_parents, | ||
726 | .ctl_reg = CM_V3DCTL, | ||
727 | .div_reg = CM_V3DDIV, | ||
728 | .int_bits = 4, | ||
729 | .frac_bits = 8, | ||
730 | }; | ||
731 | |||
732 | static const struct bcm2835_clock_data bcm2835_clock_isp_data = { | ||
733 | .name = "isp", | ||
734 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), | ||
735 | .parents = bcm2835_clock_vpu_parents, | ||
736 | .ctl_reg = CM_ISPCTL, | ||
737 | .div_reg = CM_ISPDIV, | ||
738 | .int_bits = 4, | ||
739 | .frac_bits = 8, | ||
740 | }; | ||
741 | |||
742 | static const struct bcm2835_clock_data bcm2835_clock_h264_data = { | ||
743 | .name = "h264", | ||
744 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), | ||
745 | .parents = bcm2835_clock_vpu_parents, | ||
746 | .ctl_reg = CM_H264CTL, | ||
747 | .div_reg = CM_H264DIV, | ||
748 | .int_bits = 4, | ||
749 | .frac_bits = 8, | ||
750 | }; | ||
751 | |||
752 | /* TV encoder clock. Only operating frequency is 108Mhz. */ | ||
753 | static const struct bcm2835_clock_data bcm2835_clock_vec_data = { | ||
754 | .name = "vec", | ||
755 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), | ||
756 | .parents = bcm2835_clock_per_parents, | ||
757 | .ctl_reg = CM_VECCTL, | ||
758 | .div_reg = CM_VECDIV, | ||
759 | .int_bits = 4, | ||
760 | .frac_bits = 0, | ||
761 | }; | ||
762 | |||
763 | static const struct bcm2835_clock_data bcm2835_clock_uart_data = { | ||
764 | .name = "uart", | ||
765 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), | ||
766 | .parents = bcm2835_clock_per_parents, | ||
767 | .ctl_reg = CM_UARTCTL, | ||
768 | .div_reg = CM_UARTDIV, | ||
769 | .int_bits = 10, | ||
770 | .frac_bits = 12, | ||
771 | }; | ||
772 | |||
773 | /* HDMI state machine */ | ||
774 | static const struct bcm2835_clock_data bcm2835_clock_hsm_data = { | ||
775 | .name = "hsm", | ||
776 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), | ||
777 | .parents = bcm2835_clock_per_parents, | ||
778 | .ctl_reg = CM_HSMCTL, | ||
779 | .div_reg = CM_HSMDIV, | ||
780 | .int_bits = 4, | ||
781 | .frac_bits = 8, | ||
782 | }; | ||
783 | |||
784 | /* | ||
785 | * Secondary SDRAM clock. Used for low-voltage modes when the PLL in | ||
786 | * the SDRAM controller can't be used. | ||
787 | */ | ||
788 | static const struct bcm2835_clock_data bcm2835_clock_sdram_data = { | ||
789 | .name = "sdram", | ||
790 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), | ||
791 | .parents = bcm2835_clock_vpu_parents, | ||
792 | .ctl_reg = CM_SDCCTL, | ||
793 | .div_reg = CM_SDCDIV, | ||
794 | .int_bits = 6, | ||
795 | .frac_bits = 0, | ||
796 | }; | ||
797 | |||
798 | /* Clock for the temperature sensor. Generally run at 2Mhz, max 5Mhz. */ | ||
799 | static const struct bcm2835_clock_data bcm2835_clock_tsens_data = { | ||
800 | .name = "tsens", | ||
801 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), | ||
802 | .parents = bcm2835_clock_osc_parents, | ||
803 | .ctl_reg = CM_TSENSCTL, | ||
804 | .div_reg = CM_TSENSDIV, | ||
805 | .int_bits = 5, | ||
806 | .frac_bits = 0, | ||
807 | }; | ||
808 | |||
809 | /* Arasan EMMC clock */ | ||
810 | static const struct bcm2835_clock_data bcm2835_clock_emmc_data = { | ||
811 | .name = "emmc", | ||
812 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), | ||
813 | .parents = bcm2835_clock_per_parents, | ||
814 | .ctl_reg = CM_EMMCCTL, | ||
815 | .div_reg = CM_EMMCDIV, | ||
816 | .int_bits = 4, | ||
817 | .frac_bits = 8, | ||
818 | }; | ||
819 | 453 | ||
820 | static const struct bcm2835_clock_data bcm2835_clock_pwm_data = { | 454 | u32 ctl_reg; |
821 | .name = "pwm", | ||
822 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), | ||
823 | .parents = bcm2835_clock_per_parents, | ||
824 | .ctl_reg = CM_PWMCTL, | ||
825 | .div_reg = CM_PWMDIV, | ||
826 | .int_bits = 12, | ||
827 | .frac_bits = 12, | ||
828 | }; | 455 | }; |
829 | 456 | ||
830 | struct bcm2835_pll { | 457 | struct bcm2835_pll { |
@@ -910,8 +537,14 @@ static void bcm2835_pll_off(struct clk_hw *hw) | |||
910 | struct bcm2835_cprman *cprman = pll->cprman; | 537 | struct bcm2835_cprman *cprman = pll->cprman; |
911 | const struct bcm2835_pll_data *data = pll->data; | 538 | const struct bcm2835_pll_data *data = pll->data; |
912 | 539 | ||
913 | cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST); | 540 | spin_lock(&cprman->regs_lock); |
914 | cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN); | 541 | cprman_write(cprman, data->cm_ctrl_reg, |
542 | cprman_read(cprman, data->cm_ctrl_reg) | | ||
543 | CM_PLL_ANARST); | ||
544 | cprman_write(cprman, data->a2w_ctrl_reg, | ||
545 | cprman_read(cprman, data->a2w_ctrl_reg) | | ||
546 | A2W_PLL_CTRL_PWRDN); | ||
547 | spin_unlock(&cprman->regs_lock); | ||
915 | } | 548 | } |
916 | 549 | ||
917 | static int bcm2835_pll_on(struct clk_hw *hw) | 550 | static int bcm2835_pll_on(struct clk_hw *hw) |
@@ -921,6 +554,10 @@ static int bcm2835_pll_on(struct clk_hw *hw) | |||
921 | const struct bcm2835_pll_data *data = pll->data; | 554 | const struct bcm2835_pll_data *data = pll->data; |
922 | ktime_t timeout; | 555 | ktime_t timeout; |
923 | 556 | ||
557 | cprman_write(cprman, data->a2w_ctrl_reg, | ||
558 | cprman_read(cprman, data->a2w_ctrl_reg) & | ||
559 | ~A2W_PLL_CTRL_PWRDN); | ||
560 | |||
924 | /* Take the PLL out of reset. */ | 561 | /* Take the PLL out of reset. */ |
925 | cprman_write(cprman, data->cm_ctrl_reg, | 562 | cprman_write(cprman, data->cm_ctrl_reg, |
926 | cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST); | 563 | cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST); |
@@ -1030,6 +667,36 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, | |||
1030 | return 0; | 667 | return 0; |
1031 | } | 668 | } |
1032 | 669 | ||
670 | static int bcm2835_pll_debug_init(struct clk_hw *hw, | ||
671 | struct dentry *dentry) | ||
672 | { | ||
673 | struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); | ||
674 | struct bcm2835_cprman *cprman = pll->cprman; | ||
675 | const struct bcm2835_pll_data *data = pll->data; | ||
676 | struct debugfs_reg32 *regs; | ||
677 | |||
678 | regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL); | ||
679 | if (!regs) | ||
680 | return -ENOMEM; | ||
681 | |||
682 | regs[0].name = "cm_ctrl"; | ||
683 | regs[0].offset = data->cm_ctrl_reg; | ||
684 | regs[1].name = "a2w_ctrl"; | ||
685 | regs[1].offset = data->a2w_ctrl_reg; | ||
686 | regs[2].name = "frac"; | ||
687 | regs[2].offset = data->frac_reg; | ||
688 | regs[3].name = "ana0"; | ||
689 | regs[3].offset = data->ana_reg_base + 0 * 4; | ||
690 | regs[4].name = "ana1"; | ||
691 | regs[4].offset = data->ana_reg_base + 1 * 4; | ||
692 | regs[5].name = "ana2"; | ||
693 | regs[5].offset = data->ana_reg_base + 2 * 4; | ||
694 | regs[6].name = "ana3"; | ||
695 | regs[6].offset = data->ana_reg_base + 3 * 4; | ||
696 | |||
697 | return bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry); | ||
698 | } | ||
699 | |||
1033 | static const struct clk_ops bcm2835_pll_clk_ops = { | 700 | static const struct clk_ops bcm2835_pll_clk_ops = { |
1034 | .is_prepared = bcm2835_pll_is_on, | 701 | .is_prepared = bcm2835_pll_is_on, |
1035 | .prepare = bcm2835_pll_on, | 702 | .prepare = bcm2835_pll_on, |
@@ -1037,6 +704,7 @@ static const struct clk_ops bcm2835_pll_clk_ops = { | |||
1037 | .recalc_rate = bcm2835_pll_get_rate, | 704 | .recalc_rate = bcm2835_pll_get_rate, |
1038 | .set_rate = bcm2835_pll_set_rate, | 705 | .set_rate = bcm2835_pll_set_rate, |
1039 | .round_rate = bcm2835_pll_round_rate, | 706 | .round_rate = bcm2835_pll_round_rate, |
707 | .debug_init = bcm2835_pll_debug_init, | ||
1040 | }; | 708 | }; |
1041 | 709 | ||
1042 | struct bcm2835_pll_divider { | 710 | struct bcm2835_pll_divider { |
@@ -1079,10 +747,12 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw) | |||
1079 | struct bcm2835_cprman *cprman = divider->cprman; | 747 | struct bcm2835_cprman *cprman = divider->cprman; |
1080 | const struct bcm2835_pll_divider_data *data = divider->data; | 748 | const struct bcm2835_pll_divider_data *data = divider->data; |
1081 | 749 | ||
750 | spin_lock(&cprman->regs_lock); | ||
1082 | cprman_write(cprman, data->cm_reg, | 751 | cprman_write(cprman, data->cm_reg, |
1083 | (cprman_read(cprman, data->cm_reg) & | 752 | (cprman_read(cprman, data->cm_reg) & |
1084 | ~data->load_mask) | data->hold_mask); | 753 | ~data->load_mask) | data->hold_mask); |
1085 | cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE); | 754 | cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE); |
755 | spin_unlock(&cprman->regs_lock); | ||
1086 | } | 756 | } |
1087 | 757 | ||
1088 | static int bcm2835_pll_divider_on(struct clk_hw *hw) | 758 | static int bcm2835_pll_divider_on(struct clk_hw *hw) |
@@ -1091,12 +761,14 @@ static int bcm2835_pll_divider_on(struct clk_hw *hw) | |||
1091 | struct bcm2835_cprman *cprman = divider->cprman; | 761 | struct bcm2835_cprman *cprman = divider->cprman; |
1092 | const struct bcm2835_pll_divider_data *data = divider->data; | 762 | const struct bcm2835_pll_divider_data *data = divider->data; |
1093 | 763 | ||
764 | spin_lock(&cprman->regs_lock); | ||
1094 | cprman_write(cprman, data->a2w_reg, | 765 | cprman_write(cprman, data->a2w_reg, |
1095 | cprman_read(cprman, data->a2w_reg) & | 766 | cprman_read(cprman, data->a2w_reg) & |
1096 | ~A2W_PLL_CHANNEL_DISABLE); | 767 | ~A2W_PLL_CHANNEL_DISABLE); |
1097 | 768 | ||
1098 | cprman_write(cprman, data->cm_reg, | 769 | cprman_write(cprman, data->cm_reg, |
1099 | cprman_read(cprman, data->cm_reg) & ~data->hold_mask); | 770 | cprman_read(cprman, data->cm_reg) & ~data->hold_mask); |
771 | spin_unlock(&cprman->regs_lock); | ||
1100 | 772 | ||
1101 | return 0; | 773 | return 0; |
1102 | } | 774 | } |
@@ -1124,6 +796,26 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw, | |||
1124 | return 0; | 796 | return 0; |
1125 | } | 797 | } |
1126 | 798 | ||
799 | static int bcm2835_pll_divider_debug_init(struct clk_hw *hw, | ||
800 | struct dentry *dentry) | ||
801 | { | ||
802 | struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw); | ||
803 | struct bcm2835_cprman *cprman = divider->cprman; | ||
804 | const struct bcm2835_pll_divider_data *data = divider->data; | ||
805 | struct debugfs_reg32 *regs; | ||
806 | |||
807 | regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL); | ||
808 | if (!regs) | ||
809 | return -ENOMEM; | ||
810 | |||
811 | regs[0].name = "cm"; | ||
812 | regs[0].offset = data->cm_reg; | ||
813 | regs[1].name = "a2w"; | ||
814 | regs[1].offset = data->a2w_reg; | ||
815 | |||
816 | return bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry); | ||
817 | } | ||
818 | |||
1127 | static const struct clk_ops bcm2835_pll_divider_clk_ops = { | 819 | static const struct clk_ops bcm2835_pll_divider_clk_ops = { |
1128 | .is_prepared = bcm2835_pll_divider_is_on, | 820 | .is_prepared = bcm2835_pll_divider_is_on, |
1129 | .prepare = bcm2835_pll_divider_on, | 821 | .prepare = bcm2835_pll_divider_on, |
@@ -1131,6 +823,7 @@ static const struct clk_ops bcm2835_pll_divider_clk_ops = { | |||
1131 | .recalc_rate = bcm2835_pll_divider_get_rate, | 823 | .recalc_rate = bcm2835_pll_divider_get_rate, |
1132 | .set_rate = bcm2835_pll_divider_set_rate, | 824 | .set_rate = bcm2835_pll_divider_set_rate, |
1133 | .round_rate = bcm2835_pll_divider_round_rate, | 825 | .round_rate = bcm2835_pll_divider_round_rate, |
826 | .debug_init = bcm2835_pll_divider_debug_init, | ||
1134 | }; | 827 | }; |
1135 | 828 | ||
1136 | /* | 829 | /* |
@@ -1170,7 +863,7 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, | |||
1170 | GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1; | 863 | GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1; |
1171 | u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS; | 864 | u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS; |
1172 | u64 rem; | 865 | u64 rem; |
1173 | u32 div; | 866 | u32 div, mindiv, maxdiv; |
1174 | 867 | ||
1175 | rem = do_div(temp, rate); | 868 | rem = do_div(temp, rate); |
1176 | div = temp; | 869 | div = temp; |
@@ -1180,10 +873,23 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, | |||
1180 | div += unused_frac_mask + 1; | 873 | div += unused_frac_mask + 1; |
1181 | div &= ~unused_frac_mask; | 874 | div &= ~unused_frac_mask; |
1182 | 875 | ||
1183 | /* Clamp to the limits. */ | 876 | /* different clamping limits apply for a mash clock */ |
1184 | div = max(div, unused_frac_mask + 1); | 877 | if (data->is_mash_clock) { |
1185 | div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1, | 878 | /* clamp to min divider of 2 */ |
1186 | CM_DIV_FRAC_BITS - data->frac_bits)); | 879 | mindiv = 2 << CM_DIV_FRAC_BITS; |
880 | /* clamp to the highest possible integer divider */ | ||
881 | maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS; | ||
882 | } else { | ||
883 | /* clamp to min divider of 1 */ | ||
884 | mindiv = 1 << CM_DIV_FRAC_BITS; | ||
885 | /* clamp to the highest possible fractional divider */ | ||
886 | maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1, | ||
887 | CM_DIV_FRAC_BITS - data->frac_bits); | ||
888 | } | ||
889 | |||
890 | /* apply the clamping limits */ | ||
891 | div = max_t(u32, div, mindiv); | ||
892 | div = min_t(u32, div, maxdiv); | ||
1187 | 893 | ||
1188 | return div; | 894 | return div; |
1189 | } | 895 | } |
@@ -1277,14 +983,31 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, | |||
1277 | struct bcm2835_cprman *cprman = clock->cprman; | 983 | struct bcm2835_cprman *cprman = clock->cprman; |
1278 | const struct bcm2835_clock_data *data = clock->data; | 984 | const struct bcm2835_clock_data *data = clock->data; |
1279 | u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false); | 985 | u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false); |
986 | u32 ctl; | ||
987 | |||
988 | spin_lock(&cprman->regs_lock); | ||
989 | |||
990 | /* | ||
991 | * Setting up frac support | ||
992 | * | ||
993 | * In principle it is recommended to stop/start the clock first, | ||
994 | * but as we set CLK_SET_RATE_GATE during registration of the | ||
995 | * clock this requirement should be take care of by the | ||
996 | * clk-framework. | ||
997 | */ | ||
998 | ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC; | ||
999 | ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0; | ||
1000 | cprman_write(cprman, data->ctl_reg, ctl); | ||
1280 | 1001 | ||
1281 | cprman_write(cprman, data->div_reg, div); | 1002 | cprman_write(cprman, data->div_reg, div); |
1282 | 1003 | ||
1004 | spin_unlock(&cprman->regs_lock); | ||
1005 | |||
1283 | return 0; | 1006 | return 0; |
1284 | } | 1007 | } |
1285 | 1008 | ||
1286 | static int bcm2835_clock_determine_rate(struct clk_hw *hw, | 1009 | static int bcm2835_clock_determine_rate(struct clk_hw *hw, |
1287 | struct clk_rate_request *req) | 1010 | struct clk_rate_request *req) |
1288 | { | 1011 | { |
1289 | struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); | 1012 | struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); |
1290 | struct clk_hw *parent, *best_parent = NULL; | 1013 | struct clk_hw *parent, *best_parent = NULL; |
@@ -1342,6 +1065,30 @@ static u8 bcm2835_clock_get_parent(struct clk_hw *hw) | |||
1342 | return (src & CM_SRC_MASK) >> CM_SRC_SHIFT; | 1065 | return (src & CM_SRC_MASK) >> CM_SRC_SHIFT; |
1343 | } | 1066 | } |
1344 | 1067 | ||
1068 | static struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = { | ||
1069 | { | ||
1070 | .name = "ctl", | ||
1071 | .offset = 0, | ||
1072 | }, | ||
1073 | { | ||
1074 | .name = "div", | ||
1075 | .offset = 4, | ||
1076 | }, | ||
1077 | }; | ||
1078 | |||
1079 | static int bcm2835_clock_debug_init(struct clk_hw *hw, | ||
1080 | struct dentry *dentry) | ||
1081 | { | ||
1082 | struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); | ||
1083 | struct bcm2835_cprman *cprman = clock->cprman; | ||
1084 | const struct bcm2835_clock_data *data = clock->data; | ||
1085 | |||
1086 | return bcm2835_debugfs_regset( | ||
1087 | cprman, data->ctl_reg, | ||
1088 | bcm2835_debugfs_clock_reg32, | ||
1089 | ARRAY_SIZE(bcm2835_debugfs_clock_reg32), | ||
1090 | dentry); | ||
1091 | } | ||
1345 | 1092 | ||
1346 | static const struct clk_ops bcm2835_clock_clk_ops = { | 1093 | static const struct clk_ops bcm2835_clock_clk_ops = { |
1347 | .is_prepared = bcm2835_clock_is_on, | 1094 | .is_prepared = bcm2835_clock_is_on, |
@@ -1352,6 +1099,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = { | |||
1352 | .determine_rate = bcm2835_clock_determine_rate, | 1099 | .determine_rate = bcm2835_clock_determine_rate, |
1353 | .set_parent = bcm2835_clock_set_parent, | 1100 | .set_parent = bcm2835_clock_set_parent, |
1354 | .get_parent = bcm2835_clock_get_parent, | 1101 | .get_parent = bcm2835_clock_get_parent, |
1102 | .debug_init = bcm2835_clock_debug_init, | ||
1355 | }; | 1103 | }; |
1356 | 1104 | ||
1357 | static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) | 1105 | static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) |
@@ -1370,6 +1118,7 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { | |||
1370 | .determine_rate = bcm2835_clock_determine_rate, | 1118 | .determine_rate = bcm2835_clock_determine_rate, |
1371 | .set_parent = bcm2835_clock_set_parent, | 1119 | .set_parent = bcm2835_clock_set_parent, |
1372 | .get_parent = bcm2835_clock_get_parent, | 1120 | .get_parent = bcm2835_clock_get_parent, |
1121 | .debug_init = bcm2835_clock_debug_init, | ||
1373 | }; | 1122 | }; |
1374 | 1123 | ||
1375 | static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman, | 1124 | static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman, |
@@ -1418,7 +1167,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, | |||
1418 | 1167 | ||
1419 | memset(&init, 0, sizeof(init)); | 1168 | memset(&init, 0, sizeof(init)); |
1420 | 1169 | ||
1421 | init.parent_names = &data->source_pll->name; | 1170 | init.parent_names = &data->source_pll; |
1422 | init.num_parents = 1; | 1171 | init.num_parents = 1; |
1423 | init.name = divider_name; | 1172 | init.name = divider_name; |
1424 | init.ops = &bcm2835_pll_divider_clk_ops; | 1173 | init.ops = &bcm2835_pll_divider_clk_ops; |
@@ -1501,14 +1250,559 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman, | |||
1501 | return devm_clk_register(cprman->dev, &clock->hw); | 1250 | return devm_clk_register(cprman->dev, &clock->hw); |
1502 | } | 1251 | } |
1503 | 1252 | ||
1253 | static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman, | ||
1254 | const struct bcm2835_gate_data *data) | ||
1255 | { | ||
1256 | return clk_register_gate(cprman->dev, data->name, data->parent, | ||
1257 | CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, | ||
1258 | cprman->regs + data->ctl_reg, | ||
1259 | CM_GATE_BIT, 0, &cprman->regs_lock); | ||
1260 | } | ||
1261 | |||
1262 | typedef struct clk *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman, | ||
1263 | const void *data); | ||
1264 | struct bcm2835_clk_desc { | ||
1265 | bcm2835_clk_register clk_register; | ||
1266 | const void *data; | ||
1267 | }; | ||
1268 | |||
1269 | /* assignment helper macros for different clock types */ | ||
1270 | #define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \ | ||
1271 | .data = __VA_ARGS__ } | ||
1272 | #define REGISTER_PLL(...) _REGISTER(&bcm2835_register_pll, \ | ||
1273 | &(struct bcm2835_pll_data) \ | ||
1274 | {__VA_ARGS__}) | ||
1275 | #define REGISTER_PLL_DIV(...) _REGISTER(&bcm2835_register_pll_divider, \ | ||
1276 | &(struct bcm2835_pll_divider_data) \ | ||
1277 | {__VA_ARGS__}) | ||
1278 | #define REGISTER_CLK(...) _REGISTER(&bcm2835_register_clock, \ | ||
1279 | &(struct bcm2835_clock_data) \ | ||
1280 | {__VA_ARGS__}) | ||
1281 | #define REGISTER_GATE(...) _REGISTER(&bcm2835_register_gate, \ | ||
1282 | &(struct bcm2835_gate_data) \ | ||
1283 | {__VA_ARGS__}) | ||
1284 | |||
1285 | /* parent mux arrays plus helper macros */ | ||
1286 | |||
1287 | /* main oscillator parent mux */ | ||
1288 | static const char *const bcm2835_clock_osc_parents[] = { | ||
1289 | "gnd", | ||
1290 | "xosc", | ||
1291 | "testdebug0", | ||
1292 | "testdebug1" | ||
1293 | }; | ||
1294 | |||
1295 | #define REGISTER_OSC_CLK(...) REGISTER_CLK( \ | ||
1296 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), \ | ||
1297 | .parents = bcm2835_clock_osc_parents, \ | ||
1298 | __VA_ARGS__) | ||
1299 | |||
1300 | /* main peripherial parent mux */ | ||
1301 | static const char *const bcm2835_clock_per_parents[] = { | ||
1302 | "gnd", | ||
1303 | "xosc", | ||
1304 | "testdebug0", | ||
1305 | "testdebug1", | ||
1306 | "plla_per", | ||
1307 | "pllc_per", | ||
1308 | "plld_per", | ||
1309 | "pllh_aux", | ||
1310 | }; | ||
1311 | |||
1312 | #define REGISTER_PER_CLK(...) REGISTER_CLK( \ | ||
1313 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), \ | ||
1314 | .parents = bcm2835_clock_per_parents, \ | ||
1315 | __VA_ARGS__) | ||
1316 | |||
1317 | /* main vpu parent mux */ | ||
1318 | static const char *const bcm2835_clock_vpu_parents[] = { | ||
1319 | "gnd", | ||
1320 | "xosc", | ||
1321 | "testdebug0", | ||
1322 | "testdebug1", | ||
1323 | "plla_core", | ||
1324 | "pllc_core0", | ||
1325 | "plld_core", | ||
1326 | "pllh_aux", | ||
1327 | "pllc_core1", | ||
1328 | "pllc_core2", | ||
1329 | }; | ||
1330 | |||
1331 | #define REGISTER_VPU_CLK(...) REGISTER_CLK( \ | ||
1332 | .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), \ | ||
1333 | .parents = bcm2835_clock_vpu_parents, \ | ||
1334 | __VA_ARGS__) | ||
1335 | |||
1336 | /* | ||
1337 | * the real definition of all the pll, pll_dividers and clocks | ||
1338 | * these make use of the above REGISTER_* macros | ||
1339 | */ | ||
1340 | static const struct bcm2835_clk_desc clk_desc_array[] = { | ||
1341 | /* the PLL + PLL dividers */ | ||
1342 | |||
1343 | /* | ||
1344 | * PLLA is the auxiliary PLL, used to drive the CCP2 | ||
1345 | * (Compact Camera Port 2) transmitter clock. | ||
1346 | * | ||
1347 | * It is in the PX LDO power domain, which is on when the | ||
1348 | * AUDIO domain is on. | ||
1349 | */ | ||
1350 | [BCM2835_PLLA] = REGISTER_PLL( | ||
1351 | .name = "plla", | ||
1352 | .cm_ctrl_reg = CM_PLLA, | ||
1353 | .a2w_ctrl_reg = A2W_PLLA_CTRL, | ||
1354 | .frac_reg = A2W_PLLA_FRAC, | ||
1355 | .ana_reg_base = A2W_PLLA_ANA0, | ||
1356 | .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE, | ||
1357 | .lock_mask = CM_LOCK_FLOCKA, | ||
1358 | |||
1359 | .ana = &bcm2835_ana_default, | ||
1360 | |||
1361 | .min_rate = 600000000u, | ||
1362 | .max_rate = 2400000000u, | ||
1363 | .max_fb_rate = BCM2835_MAX_FB_RATE), | ||
1364 | [BCM2835_PLLA_CORE] = REGISTER_PLL_DIV( | ||
1365 | .name = "plla_core", | ||
1366 | .source_pll = "plla", | ||
1367 | .cm_reg = CM_PLLA, | ||
1368 | .a2w_reg = A2W_PLLA_CORE, | ||
1369 | .load_mask = CM_PLLA_LOADCORE, | ||
1370 | .hold_mask = CM_PLLA_HOLDCORE, | ||
1371 | .fixed_divider = 1), | ||
1372 | [BCM2835_PLLA_PER] = REGISTER_PLL_DIV( | ||
1373 | .name = "plla_per", | ||
1374 | .source_pll = "plla", | ||
1375 | .cm_reg = CM_PLLA, | ||
1376 | .a2w_reg = A2W_PLLA_PER, | ||
1377 | .load_mask = CM_PLLA_LOADPER, | ||
1378 | .hold_mask = CM_PLLA_HOLDPER, | ||
1379 | .fixed_divider = 1), | ||
1380 | [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV( | ||
1381 | .name = "plla_dsi0", | ||
1382 | .source_pll = "plla", | ||
1383 | .cm_reg = CM_PLLA, | ||
1384 | .a2w_reg = A2W_PLLA_DSI0, | ||
1385 | .load_mask = CM_PLLA_LOADDSI0, | ||
1386 | .hold_mask = CM_PLLA_HOLDDSI0, | ||
1387 | .fixed_divider = 1), | ||
1388 | [BCM2835_PLLA_CCP2] = REGISTER_PLL_DIV( | ||
1389 | .name = "plla_ccp2", | ||
1390 | .source_pll = "plla", | ||
1391 | .cm_reg = CM_PLLA, | ||
1392 | .a2w_reg = A2W_PLLA_CCP2, | ||
1393 | .load_mask = CM_PLLA_LOADCCP2, | ||
1394 | .hold_mask = CM_PLLA_HOLDCCP2, | ||
1395 | .fixed_divider = 1), | ||
1396 | |||
1397 | /* PLLB is used for the ARM's clock. */ | ||
1398 | [BCM2835_PLLB] = REGISTER_PLL( | ||
1399 | .name = "pllb", | ||
1400 | .cm_ctrl_reg = CM_PLLB, | ||
1401 | .a2w_ctrl_reg = A2W_PLLB_CTRL, | ||
1402 | .frac_reg = A2W_PLLB_FRAC, | ||
1403 | .ana_reg_base = A2W_PLLB_ANA0, | ||
1404 | .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE, | ||
1405 | .lock_mask = CM_LOCK_FLOCKB, | ||
1406 | |||
1407 | .ana = &bcm2835_ana_default, | ||
1408 | |||
1409 | .min_rate = 600000000u, | ||
1410 | .max_rate = 3000000000u, | ||
1411 | .max_fb_rate = BCM2835_MAX_FB_RATE), | ||
1412 | [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV( | ||
1413 | .name = "pllb_arm", | ||
1414 | .source_pll = "pllb", | ||
1415 | .cm_reg = CM_PLLB, | ||
1416 | .a2w_reg = A2W_PLLB_ARM, | ||
1417 | .load_mask = CM_PLLB_LOADARM, | ||
1418 | .hold_mask = CM_PLLB_HOLDARM, | ||
1419 | .fixed_divider = 1), | ||
1420 | |||
1421 | /* | ||
1422 | * PLLC is the core PLL, used to drive the core VPU clock. | ||
1423 | * | ||
1424 | * It is in the PX LDO power domain, which is on when the | ||
1425 | * AUDIO domain is on. | ||
1426 | */ | ||
1427 | [BCM2835_PLLC] = REGISTER_PLL( | ||
1428 | .name = "pllc", | ||
1429 | .cm_ctrl_reg = CM_PLLC, | ||
1430 | .a2w_ctrl_reg = A2W_PLLC_CTRL, | ||
1431 | .frac_reg = A2W_PLLC_FRAC, | ||
1432 | .ana_reg_base = A2W_PLLC_ANA0, | ||
1433 | .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, | ||
1434 | .lock_mask = CM_LOCK_FLOCKC, | ||
1435 | |||
1436 | .ana = &bcm2835_ana_default, | ||
1437 | |||
1438 | .min_rate = 600000000u, | ||
1439 | .max_rate = 3000000000u, | ||
1440 | .max_fb_rate = BCM2835_MAX_FB_RATE), | ||
1441 | [BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV( | ||
1442 | .name = "pllc_core0", | ||
1443 | .source_pll = "pllc", | ||
1444 | .cm_reg = CM_PLLC, | ||
1445 | .a2w_reg = A2W_PLLC_CORE0, | ||
1446 | .load_mask = CM_PLLC_LOADCORE0, | ||
1447 | .hold_mask = CM_PLLC_HOLDCORE0, | ||
1448 | .fixed_divider = 1), | ||
1449 | [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV( | ||
1450 | .name = "pllc_core1", | ||
1451 | .source_pll = "pllc", | ||
1452 | .cm_reg = CM_PLLC, | ||
1453 | .a2w_reg = A2W_PLLC_CORE1, | ||
1454 | .load_mask = CM_PLLC_LOADCORE1, | ||
1455 | .hold_mask = CM_PLLC_HOLDCORE1, | ||
1456 | .fixed_divider = 1), | ||
1457 | [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV( | ||
1458 | .name = "pllc_core2", | ||
1459 | .source_pll = "pllc", | ||
1460 | .cm_reg = CM_PLLC, | ||
1461 | .a2w_reg = A2W_PLLC_CORE2, | ||
1462 | .load_mask = CM_PLLC_LOADCORE2, | ||
1463 | .hold_mask = CM_PLLC_HOLDCORE2, | ||
1464 | .fixed_divider = 1), | ||
1465 | [BCM2835_PLLC_PER] = REGISTER_PLL_DIV( | ||
1466 | .name = "pllc_per", | ||
1467 | .source_pll = "pllc", | ||
1468 | .cm_reg = CM_PLLC, | ||
1469 | .a2w_reg = A2W_PLLC_PER, | ||
1470 | .load_mask = CM_PLLC_LOADPER, | ||
1471 | .hold_mask = CM_PLLC_HOLDPER, | ||
1472 | .fixed_divider = 1), | ||
1473 | |||
1474 | /* | ||
1475 | * PLLD is the display PLL, used to drive DSI display panels. | ||
1476 | * | ||
1477 | * It is in the PX LDO power domain, which is on when the | ||
1478 | * AUDIO domain is on. | ||
1479 | */ | ||
1480 | [BCM2835_PLLD] = REGISTER_PLL( | ||
1481 | .name = "plld", | ||
1482 | .cm_ctrl_reg = CM_PLLD, | ||
1483 | .a2w_ctrl_reg = A2W_PLLD_CTRL, | ||
1484 | .frac_reg = A2W_PLLD_FRAC, | ||
1485 | .ana_reg_base = A2W_PLLD_ANA0, | ||
1486 | .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE, | ||
1487 | .lock_mask = CM_LOCK_FLOCKD, | ||
1488 | |||
1489 | .ana = &bcm2835_ana_default, | ||
1490 | |||
1491 | .min_rate = 600000000u, | ||
1492 | .max_rate = 2400000000u, | ||
1493 | .max_fb_rate = BCM2835_MAX_FB_RATE), | ||
1494 | [BCM2835_PLLD_CORE] = REGISTER_PLL_DIV( | ||
1495 | .name = "plld_core", | ||
1496 | .source_pll = "plld", | ||
1497 | .cm_reg = CM_PLLD, | ||
1498 | .a2w_reg = A2W_PLLD_CORE, | ||
1499 | .load_mask = CM_PLLD_LOADCORE, | ||
1500 | .hold_mask = CM_PLLD_HOLDCORE, | ||
1501 | .fixed_divider = 1), | ||
1502 | [BCM2835_PLLD_PER] = REGISTER_PLL_DIV( | ||
1503 | .name = "plld_per", | ||
1504 | .source_pll = "plld", | ||
1505 | .cm_reg = CM_PLLD, | ||
1506 | .a2w_reg = A2W_PLLD_PER, | ||
1507 | .load_mask = CM_PLLD_LOADPER, | ||
1508 | .hold_mask = CM_PLLD_HOLDPER, | ||
1509 | .fixed_divider = 1), | ||
1510 | [BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV( | ||
1511 | .name = "plld_dsi0", | ||
1512 | .source_pll = "plld", | ||
1513 | .cm_reg = CM_PLLD, | ||
1514 | .a2w_reg = A2W_PLLD_DSI0, | ||
1515 | .load_mask = CM_PLLD_LOADDSI0, | ||
1516 | .hold_mask = CM_PLLD_HOLDDSI0, | ||
1517 | .fixed_divider = 1), | ||
1518 | [BCM2835_PLLD_DSI1] = REGISTER_PLL_DIV( | ||
1519 | .name = "plld_dsi1", | ||
1520 | .source_pll = "plld", | ||
1521 | .cm_reg = CM_PLLD, | ||
1522 | .a2w_reg = A2W_PLLD_DSI1, | ||
1523 | .load_mask = CM_PLLD_LOADDSI1, | ||
1524 | .hold_mask = CM_PLLD_HOLDDSI1, | ||
1525 | .fixed_divider = 1), | ||
1526 | |||
1527 | /* | ||
1528 | * PLLH is used to supply the pixel clock or the AUX clock for the | ||
1529 | * TV encoder. | ||
1530 | * | ||
1531 | * It is in the HDMI power domain. | ||
1532 | */ | ||
1533 | [BCM2835_PLLH] = REGISTER_PLL( | ||
1534 | "pllh", | ||
1535 | .cm_ctrl_reg = CM_PLLH, | ||
1536 | .a2w_ctrl_reg = A2W_PLLH_CTRL, | ||
1537 | .frac_reg = A2W_PLLH_FRAC, | ||
1538 | .ana_reg_base = A2W_PLLH_ANA0, | ||
1539 | .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE, | ||
1540 | .lock_mask = CM_LOCK_FLOCKH, | ||
1541 | |||
1542 | .ana = &bcm2835_ana_pllh, | ||
1543 | |||
1544 | .min_rate = 600000000u, | ||
1545 | .max_rate = 3000000000u, | ||
1546 | .max_fb_rate = BCM2835_MAX_FB_RATE), | ||
1547 | [BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV( | ||
1548 | .name = "pllh_rcal", | ||
1549 | .source_pll = "pllh", | ||
1550 | .cm_reg = CM_PLLH, | ||
1551 | .a2w_reg = A2W_PLLH_RCAL, | ||
1552 | .load_mask = CM_PLLH_LOADRCAL, | ||
1553 | .hold_mask = 0, | ||
1554 | .fixed_divider = 10), | ||
1555 | [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV( | ||
1556 | .name = "pllh_aux", | ||
1557 | .source_pll = "pllh", | ||
1558 | .cm_reg = CM_PLLH, | ||
1559 | .a2w_reg = A2W_PLLH_AUX, | ||
1560 | .load_mask = CM_PLLH_LOADAUX, | ||
1561 | .hold_mask = 0, | ||
1562 | .fixed_divider = 10), | ||
1563 | [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV( | ||
1564 | .name = "pllh_pix", | ||
1565 | .source_pll = "pllh", | ||
1566 | .cm_reg = CM_PLLH, | ||
1567 | .a2w_reg = A2W_PLLH_PIX, | ||
1568 | .load_mask = CM_PLLH_LOADPIX, | ||
1569 | .hold_mask = 0, | ||
1570 | .fixed_divider = 10), | ||
1571 | |||
1572 | /* the clocks */ | ||
1573 | |||
1574 | /* clocks with oscillator parent mux */ | ||
1575 | |||
1576 | /* One Time Programmable Memory clock. Maximum 10Mhz. */ | ||
1577 | [BCM2835_CLOCK_OTP] = REGISTER_OSC_CLK( | ||
1578 | .name = "otp", | ||
1579 | .ctl_reg = CM_OTPCTL, | ||
1580 | .div_reg = CM_OTPDIV, | ||
1581 | .int_bits = 4, | ||
1582 | .frac_bits = 0), | ||
1583 | /* | ||
1584 | * Used for a 1Mhz clock for the system clocksource, and also used | ||
1585 | * bythe watchdog timer and the camera pulse generator. | ||
1586 | */ | ||
1587 | [BCM2835_CLOCK_TIMER] = REGISTER_OSC_CLK( | ||
1588 | .name = "timer", | ||
1589 | .ctl_reg = CM_TIMERCTL, | ||
1590 | .div_reg = CM_TIMERDIV, | ||
1591 | .int_bits = 6, | ||
1592 | .frac_bits = 12), | ||
1593 | /* | ||
1594 | * Clock for the temperature sensor. | ||
1595 | * Generally run at 2Mhz, max 5Mhz. | ||
1596 | */ | ||
1597 | [BCM2835_CLOCK_TSENS] = REGISTER_OSC_CLK( | ||
1598 | .name = "tsens", | ||
1599 | .ctl_reg = CM_TSENSCTL, | ||
1600 | .div_reg = CM_TSENSDIV, | ||
1601 | .int_bits = 5, | ||
1602 | .frac_bits = 0), | ||
1603 | [BCM2835_CLOCK_TEC] = REGISTER_OSC_CLK( | ||
1604 | .name = "tec", | ||
1605 | .ctl_reg = CM_TECCTL, | ||
1606 | .div_reg = CM_TECDIV, | ||
1607 | .int_bits = 6, | ||
1608 | .frac_bits = 0), | ||
1609 | |||
1610 | /* clocks with vpu parent mux */ | ||
1611 | [BCM2835_CLOCK_H264] = REGISTER_VPU_CLK( | ||
1612 | .name = "h264", | ||
1613 | .ctl_reg = CM_H264CTL, | ||
1614 | .div_reg = CM_H264DIV, | ||
1615 | .int_bits = 4, | ||
1616 | .frac_bits = 8), | ||
1617 | [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK( | ||
1618 | .name = "isp", | ||
1619 | .ctl_reg = CM_ISPCTL, | ||
1620 | .div_reg = CM_ISPDIV, | ||
1621 | .int_bits = 4, | ||
1622 | .frac_bits = 8), | ||
1623 | |||
1624 | /* | ||
1625 | * Secondary SDRAM clock. Used for low-voltage modes when the PLL | ||
1626 | * in the SDRAM controller can't be used. | ||
1627 | */ | ||
1628 | [BCM2835_CLOCK_SDRAM] = REGISTER_VPU_CLK( | ||
1629 | .name = "sdram", | ||
1630 | .ctl_reg = CM_SDCCTL, | ||
1631 | .div_reg = CM_SDCDIV, | ||
1632 | .int_bits = 6, | ||
1633 | .frac_bits = 0), | ||
1634 | [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK( | ||
1635 | .name = "v3d", | ||
1636 | .ctl_reg = CM_V3DCTL, | ||
1637 | .div_reg = CM_V3DDIV, | ||
1638 | .int_bits = 4, | ||
1639 | .frac_bits = 8), | ||
1640 | /* | ||
1641 | * VPU clock. This doesn't have an enable bit, since it drives | ||
1642 | * the bus for everything else, and is special so it doesn't need | ||
1643 | * to be gated for rate changes. It is also known as "clk_audio" | ||
1644 | * in various hardware documentation. | ||
1645 | */ | ||
1646 | [BCM2835_CLOCK_VPU] = REGISTER_VPU_CLK( | ||
1647 | .name = "vpu", | ||
1648 | .ctl_reg = CM_VPUCTL, | ||
1649 | .div_reg = CM_VPUDIV, | ||
1650 | .int_bits = 12, | ||
1651 | .frac_bits = 8, | ||
1652 | .is_vpu_clock = true), | ||
1653 | |||
1654 | /* clocks with per parent mux */ | ||
1655 | [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK( | ||
1656 | .name = "aveo", | ||
1657 | .ctl_reg = CM_AVEOCTL, | ||
1658 | .div_reg = CM_AVEODIV, | ||
1659 | .int_bits = 4, | ||
1660 | .frac_bits = 0), | ||
1661 | [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK( | ||
1662 | .name = "cam0", | ||
1663 | .ctl_reg = CM_CAM0CTL, | ||
1664 | .div_reg = CM_CAM0DIV, | ||
1665 | .int_bits = 4, | ||
1666 | .frac_bits = 8), | ||
1667 | [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK( | ||
1668 | .name = "cam1", | ||
1669 | .ctl_reg = CM_CAM1CTL, | ||
1670 | .div_reg = CM_CAM1DIV, | ||
1671 | .int_bits = 4, | ||
1672 | .frac_bits = 8), | ||
1673 | [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK( | ||
1674 | .name = "dft", | ||
1675 | .ctl_reg = CM_DFTCTL, | ||
1676 | .div_reg = CM_DFTDIV, | ||
1677 | .int_bits = 5, | ||
1678 | .frac_bits = 0), | ||
1679 | [BCM2835_CLOCK_DPI] = REGISTER_PER_CLK( | ||
1680 | .name = "dpi", | ||
1681 | .ctl_reg = CM_DPICTL, | ||
1682 | .div_reg = CM_DPIDIV, | ||
1683 | .int_bits = 4, | ||
1684 | .frac_bits = 8), | ||
1685 | |||
1686 | /* Arasan EMMC clock */ | ||
1687 | [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK( | ||
1688 | .name = "emmc", | ||
1689 | .ctl_reg = CM_EMMCCTL, | ||
1690 | .div_reg = CM_EMMCDIV, | ||
1691 | .int_bits = 4, | ||
1692 | .frac_bits = 8), | ||
1693 | |||
1694 | /* General purpose (GPIO) clocks */ | ||
1695 | [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK( | ||
1696 | .name = "gp0", | ||
1697 | .ctl_reg = CM_GP0CTL, | ||
1698 | .div_reg = CM_GP0DIV, | ||
1699 | .int_bits = 12, | ||
1700 | .frac_bits = 12, | ||
1701 | .is_mash_clock = true), | ||
1702 | [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK( | ||
1703 | .name = "gp1", | ||
1704 | .ctl_reg = CM_GP1CTL, | ||
1705 | .div_reg = CM_GP1DIV, | ||
1706 | .int_bits = 12, | ||
1707 | .frac_bits = 12, | ||
1708 | .is_mash_clock = true), | ||
1709 | [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( | ||
1710 | .name = "gp2", | ||
1711 | .ctl_reg = CM_GP2CTL, | ||
1712 | .div_reg = CM_GP2DIV, | ||
1713 | .int_bits = 12, | ||
1714 | .frac_bits = 12), | ||
1715 | |||
1716 | /* HDMI state machine */ | ||
1717 | [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK( | ||
1718 | .name = "hsm", | ||
1719 | .ctl_reg = CM_HSMCTL, | ||
1720 | .div_reg = CM_HSMDIV, | ||
1721 | .int_bits = 4, | ||
1722 | .frac_bits = 8), | ||
1723 | [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK( | ||
1724 | .name = "pcm", | ||
1725 | .ctl_reg = CM_PCMCTL, | ||
1726 | .div_reg = CM_PCMDIV, | ||
1727 | .int_bits = 12, | ||
1728 | .frac_bits = 12, | ||
1729 | .is_mash_clock = true), | ||
1730 | [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( | ||
1731 | .name = "pwm", | ||
1732 | .ctl_reg = CM_PWMCTL, | ||
1733 | .div_reg = CM_PWMDIV, | ||
1734 | .int_bits = 12, | ||
1735 | .frac_bits = 12, | ||
1736 | .is_mash_clock = true), | ||
1737 | [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK( | ||
1738 | .name = "slim", | ||
1739 | .ctl_reg = CM_SLIMCTL, | ||
1740 | .div_reg = CM_SLIMDIV, | ||
1741 | .int_bits = 12, | ||
1742 | .frac_bits = 12, | ||
1743 | .is_mash_clock = true), | ||
1744 | [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK( | ||
1745 | .name = "smi", | ||
1746 | .ctl_reg = CM_SMICTL, | ||
1747 | .div_reg = CM_SMIDIV, | ||
1748 | .int_bits = 4, | ||
1749 | .frac_bits = 8), | ||
1750 | [BCM2835_CLOCK_UART] = REGISTER_PER_CLK( | ||
1751 | .name = "uart", | ||
1752 | .ctl_reg = CM_UARTCTL, | ||
1753 | .div_reg = CM_UARTDIV, | ||
1754 | .int_bits = 10, | ||
1755 | .frac_bits = 12), | ||
1756 | |||
1757 | /* TV encoder clock. Only operating frequency is 108Mhz. */ | ||
1758 | [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( | ||
1759 | .name = "vec", | ||
1760 | .ctl_reg = CM_VECCTL, | ||
1761 | .div_reg = CM_VECDIV, | ||
1762 | .int_bits = 4, | ||
1763 | .frac_bits = 0), | ||
1764 | |||
1765 | /* dsi clocks */ | ||
1766 | [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK( | ||
1767 | .name = "dsi0e", | ||
1768 | .ctl_reg = CM_DSI0ECTL, | ||
1769 | .div_reg = CM_DSI0EDIV, | ||
1770 | .int_bits = 4, | ||
1771 | .frac_bits = 8), | ||
1772 | [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK( | ||
1773 | .name = "dsi1e", | ||
1774 | .ctl_reg = CM_DSI1ECTL, | ||
1775 | .div_reg = CM_DSI1EDIV, | ||
1776 | .int_bits = 4, | ||
1777 | .frac_bits = 8), | ||
1778 | |||
1779 | /* the gates */ | ||
1780 | |||
1781 | /* | ||
1782 | * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if | ||
1783 | * you have the debug bit set in the power manager, which we | ||
1784 | * don't bother exposing) are individual gates off of the | ||
1785 | * non-stop vpu clock. | ||
1786 | */ | ||
1787 | [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE( | ||
1788 | .name = "peri_image", | ||
1789 | .parent = "vpu", | ||
1790 | .ctl_reg = CM_PERIICTL), | ||
1791 | }; | ||
1792 | |||
1504 | static int bcm2835_clk_probe(struct platform_device *pdev) | 1793 | static int bcm2835_clk_probe(struct platform_device *pdev) |
1505 | { | 1794 | { |
1506 | struct device *dev = &pdev->dev; | 1795 | struct device *dev = &pdev->dev; |
1507 | struct clk **clks; | 1796 | struct clk **clks; |
1508 | struct bcm2835_cprman *cprman; | 1797 | struct bcm2835_cprman *cprman; |
1509 | struct resource *res; | 1798 | struct resource *res; |
1799 | const struct bcm2835_clk_desc *desc; | ||
1800 | const size_t asize = ARRAY_SIZE(clk_desc_array); | ||
1801 | size_t i; | ||
1510 | 1802 | ||
1511 | cprman = devm_kzalloc(dev, sizeof(*cprman), GFP_KERNEL); | 1803 | cprman = devm_kzalloc(dev, |
1804 | sizeof(*cprman) + asize * sizeof(*clks), | ||
1805 | GFP_KERNEL); | ||
1512 | if (!cprman) | 1806 | if (!cprman) |
1513 | return -ENOMEM; | 1807 | return -ENOMEM; |
1514 | 1808 | ||
@@ -1525,80 +1819,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) | |||
1525 | 1819 | ||
1526 | platform_set_drvdata(pdev, cprman); | 1820 | platform_set_drvdata(pdev, cprman); |
1527 | 1821 | ||
1528 | cprman->onecell.clk_num = BCM2835_CLOCK_COUNT; | 1822 | cprman->onecell.clk_num = asize; |
1529 | cprman->onecell.clks = cprman->clks; | 1823 | cprman->onecell.clks = cprman->clks; |
1530 | clks = cprman->clks; | 1824 | clks = cprman->clks; |
1531 | 1825 | ||
1532 | clks[BCM2835_PLLA] = bcm2835_register_pll(cprman, &bcm2835_plla_data); | 1826 | for (i = 0; i < asize; i++) { |
1533 | clks[BCM2835_PLLB] = bcm2835_register_pll(cprman, &bcm2835_pllb_data); | 1827 | desc = &clk_desc_array[i]; |
1534 | clks[BCM2835_PLLC] = bcm2835_register_pll(cprman, &bcm2835_pllc_data); | 1828 | if (desc->clk_register && desc->data) |
1535 | clks[BCM2835_PLLD] = bcm2835_register_pll(cprman, &bcm2835_plld_data); | 1829 | clks[i] = desc->clk_register(cprman, desc->data); |
1536 | clks[BCM2835_PLLH] = bcm2835_register_pll(cprman, &bcm2835_pllh_data); | 1830 | } |
1537 | |||
1538 | clks[BCM2835_PLLA_CORE] = | ||
1539 | bcm2835_register_pll_divider(cprman, &bcm2835_plla_core_data); | ||
1540 | clks[BCM2835_PLLA_PER] = | ||
1541 | bcm2835_register_pll_divider(cprman, &bcm2835_plla_per_data); | ||
1542 | clks[BCM2835_PLLC_CORE0] = | ||
1543 | bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core0_data); | ||
1544 | clks[BCM2835_PLLC_CORE1] = | ||
1545 | bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core1_data); | ||
1546 | clks[BCM2835_PLLC_CORE2] = | ||
1547 | bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core2_data); | ||
1548 | clks[BCM2835_PLLC_PER] = | ||
1549 | bcm2835_register_pll_divider(cprman, &bcm2835_pllc_per_data); | ||
1550 | clks[BCM2835_PLLD_CORE] = | ||
1551 | bcm2835_register_pll_divider(cprman, &bcm2835_plld_core_data); | ||
1552 | clks[BCM2835_PLLD_PER] = | ||
1553 | bcm2835_register_pll_divider(cprman, &bcm2835_plld_per_data); | ||
1554 | clks[BCM2835_PLLH_RCAL] = | ||
1555 | bcm2835_register_pll_divider(cprman, &bcm2835_pllh_rcal_data); | ||
1556 | clks[BCM2835_PLLH_AUX] = | ||
1557 | bcm2835_register_pll_divider(cprman, &bcm2835_pllh_aux_data); | ||
1558 | clks[BCM2835_PLLH_PIX] = | ||
1559 | bcm2835_register_pll_divider(cprman, &bcm2835_pllh_pix_data); | ||
1560 | |||
1561 | clks[BCM2835_CLOCK_TIMER] = | ||
1562 | bcm2835_register_clock(cprman, &bcm2835_clock_timer_data); | ||
1563 | clks[BCM2835_CLOCK_OTP] = | ||
1564 | bcm2835_register_clock(cprman, &bcm2835_clock_otp_data); | ||
1565 | clks[BCM2835_CLOCK_TSENS] = | ||
1566 | bcm2835_register_clock(cprman, &bcm2835_clock_tsens_data); | ||
1567 | clks[BCM2835_CLOCK_VPU] = | ||
1568 | bcm2835_register_clock(cprman, &bcm2835_clock_vpu_data); | ||
1569 | clks[BCM2835_CLOCK_V3D] = | ||
1570 | bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data); | ||
1571 | clks[BCM2835_CLOCK_ISP] = | ||
1572 | bcm2835_register_clock(cprman, &bcm2835_clock_isp_data); | ||
1573 | clks[BCM2835_CLOCK_H264] = | ||
1574 | bcm2835_register_clock(cprman, &bcm2835_clock_h264_data); | ||
1575 | clks[BCM2835_CLOCK_V3D] = | ||
1576 | bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data); | ||
1577 | clks[BCM2835_CLOCK_SDRAM] = | ||
1578 | bcm2835_register_clock(cprman, &bcm2835_clock_sdram_data); | ||
1579 | clks[BCM2835_CLOCK_UART] = | ||
1580 | bcm2835_register_clock(cprman, &bcm2835_clock_uart_data); | ||
1581 | clks[BCM2835_CLOCK_VEC] = | ||
1582 | bcm2835_register_clock(cprman, &bcm2835_clock_vec_data); | ||
1583 | clks[BCM2835_CLOCK_HSM] = | ||
1584 | bcm2835_register_clock(cprman, &bcm2835_clock_hsm_data); | ||
1585 | clks[BCM2835_CLOCK_EMMC] = | ||
1586 | bcm2835_register_clock(cprman, &bcm2835_clock_emmc_data); | ||
1587 | |||
1588 | /* | ||
1589 | * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if | ||
1590 | * you have the debug bit set in the power manager, which we | ||
1591 | * don't bother exposing) are individual gates off of the | ||
1592 | * non-stop vpu clock. | ||
1593 | */ | ||
1594 | clks[BCM2835_CLOCK_PERI_IMAGE] = | ||
1595 | clk_register_gate(dev, "peri_image", "vpu", | ||
1596 | CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, | ||
1597 | cprman->regs + CM_PERIICTL, CM_GATE_BIT, | ||
1598 | 0, &cprman->regs_lock); | ||
1599 | |||
1600 | clks[BCM2835_CLOCK_PWM] = | ||
1601 | bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data); | ||
1602 | 1831 | ||
1603 | return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, | 1832 | return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, |
1604 | &cprman->onecell); | 1833 | &cprman->onecell); |
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c index deaa7f962b84..526b0b0e9a9f 100644 --- a/drivers/clk/bcm/clk-kona-setup.c +++ b/drivers/clk/bcm/clk-kona-setup.c | |||
@@ -577,7 +577,8 @@ static u32 *parent_process(const char *clocks[], | |||
577 | * selector is not required, but we allocate space for the | 577 | * selector is not required, but we allocate space for the |
578 | * array anyway to keep things simple. | 578 | * array anyway to keep things simple. |
579 | */ | 579 | */ |
580 | parent_names = kmalloc(parent_count * sizeof(parent_names), GFP_KERNEL); | 580 | parent_names = kmalloc_array(parent_count, sizeof(*parent_names), |
581 | GFP_KERNEL); | ||
581 | if (!parent_names) { | 582 | if (!parent_names) { |
582 | pr_err("%s: error allocating %u parent names\n", __func__, | 583 | pr_err("%s: error allocating %u parent names\n", __func__, |
583 | parent_count); | 584 | parent_count); |
diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c index ff4ef4f1df62..1f60b02416a7 100644 --- a/drivers/clk/clk-clps711x.c +++ b/drivers/clk/clk-clps711x.c | |||
@@ -107,16 +107,15 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base, | |||
107 | writel(tmp, base + CLPS711X_SYSCON1); | 107 | writel(tmp, base + CLPS711X_SYSCON1); |
108 | 108 | ||
109 | clps711x_clk->clks[CLPS711X_CLK_DUMMY] = | 109 | clps711x_clk->clks[CLPS711X_CLK_DUMMY] = |
110 | clk_register_fixed_rate(NULL, "dummy", NULL, CLK_IS_ROOT, 0); | 110 | clk_register_fixed_rate(NULL, "dummy", NULL, 0, 0); |
111 | clps711x_clk->clks[CLPS711X_CLK_CPU] = | 111 | clps711x_clk->clks[CLPS711X_CLK_CPU] = |
112 | clk_register_fixed_rate(NULL, "cpu", NULL, CLK_IS_ROOT, f_cpu); | 112 | clk_register_fixed_rate(NULL, "cpu", NULL, 0, f_cpu); |
113 | clps711x_clk->clks[CLPS711X_CLK_BUS] = | 113 | clps711x_clk->clks[CLPS711X_CLK_BUS] = |
114 | clk_register_fixed_rate(NULL, "bus", NULL, CLK_IS_ROOT, f_bus); | 114 | clk_register_fixed_rate(NULL, "bus", NULL, 0, f_bus); |
115 | clps711x_clk->clks[CLPS711X_CLK_PLL] = | 115 | clps711x_clk->clks[CLPS711X_CLK_PLL] = |
116 | clk_register_fixed_rate(NULL, "pll", NULL, CLK_IS_ROOT, f_pll); | 116 | clk_register_fixed_rate(NULL, "pll", NULL, 0, f_pll); |
117 | clps711x_clk->clks[CLPS711X_CLK_TIMERREF] = | 117 | clps711x_clk->clks[CLPS711X_CLK_TIMERREF] = |
118 | clk_register_fixed_rate(NULL, "timer_ref", NULL, CLK_IS_ROOT, | 118 | clk_register_fixed_rate(NULL, "timer_ref", NULL, 0, f_tim); |
119 | f_tim); | ||
120 | clps711x_clk->clks[CLPS711X_CLK_TIMER1] = | 119 | clps711x_clk->clks[CLPS711X_CLK_TIMER1] = |
121 | clk_register_divider_table(NULL, "timer1", "timer_ref", 0, | 120 | clk_register_divider_table(NULL, "timer1", "timer_ref", 0, |
122 | base + CLPS711X_SYSCON1, 5, 1, 0, | 121 | base + CLPS711X_SYSCON1, 5, 1, 0, |
@@ -126,10 +125,9 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base, | |||
126 | base + CLPS711X_SYSCON1, 7, 1, 0, | 125 | base + CLPS711X_SYSCON1, 7, 1, 0, |
127 | timer_div_table, &clps711x_clk->lock); | 126 | timer_div_table, &clps711x_clk->lock); |
128 | clps711x_clk->clks[CLPS711X_CLK_PWM] = | 127 | clps711x_clk->clks[CLPS711X_CLK_PWM] = |
129 | clk_register_fixed_rate(NULL, "pwm", NULL, CLK_IS_ROOT, f_pwm); | 128 | clk_register_fixed_rate(NULL, "pwm", NULL, 0, f_pwm); |
130 | clps711x_clk->clks[CLPS711X_CLK_SPIREF] = | 129 | clps711x_clk->clks[CLPS711X_CLK_SPIREF] = |
131 | clk_register_fixed_rate(NULL, "spi_ref", NULL, CLK_IS_ROOT, | 130 | clk_register_fixed_rate(NULL, "spi_ref", NULL, 0, f_spi); |
132 | f_spi); | ||
133 | clps711x_clk->clks[CLPS711X_CLK_SPI] = | 131 | clps711x_clk->clks[CLPS711X_CLK_SPI] = |
134 | clk_register_divider_table(NULL, "spi", "spi_ref", 0, | 132 | clk_register_divider_table(NULL, "spi", "spi_ref", 0, |
135 | base + CLPS711X_SYSCON1, 16, 2, 0, | 133 | base + CLPS711X_SYSCON1, 16, 2, 0, |
@@ -137,8 +135,7 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base, | |||
137 | clps711x_clk->clks[CLPS711X_CLK_UART] = | 135 | clps711x_clk->clks[CLPS711X_CLK_UART] = |
138 | clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10); | 136 | clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10); |
139 | clps711x_clk->clks[CLPS711X_CLK_TICK] = | 137 | clps711x_clk->clks[CLPS711X_CLK_TICK] = |
140 | clk_register_fixed_rate(NULL, "tick", NULL, CLK_IS_ROOT, 64); | 138 | clk_register_fixed_rate(NULL, "tick", NULL, 0, 64); |
141 | |||
142 | for (i = 0; i < CLPS711X_CLK_MAX; i++) | 139 | for (i = 0; i < CLPS711X_CLK_MAX; i++) |
143 | if (IS_ERR(clps711x_clk->clks[i])) | 140 | if (IS_ERR(clps711x_clk->clks[i])) |
144 | pr_err("clk %i: register failed with %ld\n", | 141 | pr_err("clk %i: register failed with %ld\n", |
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 1f903e1f86a2..00269de2f390 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c | |||
@@ -151,6 +151,33 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate, | |||
151 | return rate_ops->set_rate(rate_hw, rate, parent_rate); | 151 | return rate_ops->set_rate(rate_hw, rate, parent_rate); |
152 | } | 152 | } |
153 | 153 | ||
154 | static int clk_composite_set_rate_and_parent(struct clk_hw *hw, | ||
155 | unsigned long rate, | ||
156 | unsigned long parent_rate, | ||
157 | u8 index) | ||
158 | { | ||
159 | struct clk_composite *composite = to_clk_composite(hw); | ||
160 | const struct clk_ops *rate_ops = composite->rate_ops; | ||
161 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
162 | struct clk_hw *rate_hw = composite->rate_hw; | ||
163 | struct clk_hw *mux_hw = composite->mux_hw; | ||
164 | unsigned long temp_rate; | ||
165 | |||
166 | __clk_hw_set_clk(rate_hw, hw); | ||
167 | __clk_hw_set_clk(mux_hw, hw); | ||
168 | |||
169 | temp_rate = rate_ops->recalc_rate(rate_hw, parent_rate); | ||
170 | if (temp_rate > rate) { | ||
171 | rate_ops->set_rate(rate_hw, rate, parent_rate); | ||
172 | mux_ops->set_parent(mux_hw, index); | ||
173 | } else { | ||
174 | mux_ops->set_parent(mux_hw, index); | ||
175 | rate_ops->set_rate(rate_hw, rate, parent_rate); | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
154 | static int clk_composite_is_enabled(struct clk_hw *hw) | 181 | static int clk_composite_is_enabled(struct clk_hw *hw) |
155 | { | 182 | { |
156 | struct clk_composite *composite = to_clk_composite(hw); | 183 | struct clk_composite *composite = to_clk_composite(hw); |
@@ -184,17 +211,18 @@ static void clk_composite_disable(struct clk_hw *hw) | |||
184 | gate_ops->disable(gate_hw); | 211 | gate_ops->disable(gate_hw); |
185 | } | 212 | } |
186 | 213 | ||
187 | struct clk *clk_register_composite(struct device *dev, const char *name, | 214 | struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, |
188 | const char * const *parent_names, int num_parents, | 215 | const char * const *parent_names, int num_parents, |
189 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | 216 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, |
190 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, | 217 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, |
191 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | 218 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, |
192 | unsigned long flags) | 219 | unsigned long flags) |
193 | { | 220 | { |
194 | struct clk *clk; | 221 | struct clk_hw *hw; |
195 | struct clk_init_data init; | 222 | struct clk_init_data init; |
196 | struct clk_composite *composite; | 223 | struct clk_composite *composite; |
197 | struct clk_ops *clk_composite_ops; | 224 | struct clk_ops *clk_composite_ops; |
225 | int ret; | ||
198 | 226 | ||
199 | composite = kzalloc(sizeof(*composite), GFP_KERNEL); | 227 | composite = kzalloc(sizeof(*composite), GFP_KERNEL); |
200 | if (!composite) | 228 | if (!composite) |
@@ -204,12 +232,13 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
204 | init.flags = flags | CLK_IS_BASIC; | 232 | init.flags = flags | CLK_IS_BASIC; |
205 | init.parent_names = parent_names; | 233 | init.parent_names = parent_names; |
206 | init.num_parents = num_parents; | 234 | init.num_parents = num_parents; |
235 | hw = &composite->hw; | ||
207 | 236 | ||
208 | clk_composite_ops = &composite->ops; | 237 | clk_composite_ops = &composite->ops; |
209 | 238 | ||
210 | if (mux_hw && mux_ops) { | 239 | if (mux_hw && mux_ops) { |
211 | if (!mux_ops->get_parent) { | 240 | if (!mux_ops->get_parent) { |
212 | clk = ERR_PTR(-EINVAL); | 241 | hw = ERR_PTR(-EINVAL); |
213 | goto err; | 242 | goto err; |
214 | } | 243 | } |
215 | 244 | ||
@@ -224,7 +253,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
224 | 253 | ||
225 | if (rate_hw && rate_ops) { | 254 | if (rate_hw && rate_ops) { |
226 | if (!rate_ops->recalc_rate) { | 255 | if (!rate_ops->recalc_rate) { |
227 | clk = ERR_PTR(-EINVAL); | 256 | hw = ERR_PTR(-EINVAL); |
228 | goto err; | 257 | goto err; |
229 | } | 258 | } |
230 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; | 259 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; |
@@ -250,10 +279,16 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
250 | composite->rate_ops = rate_ops; | 279 | composite->rate_ops = rate_ops; |
251 | } | 280 | } |
252 | 281 | ||
282 | if (mux_hw && mux_ops && rate_hw && rate_ops) { | ||
283 | if (mux_ops->set_parent && rate_ops->set_rate) | ||
284 | clk_composite_ops->set_rate_and_parent = | ||
285 | clk_composite_set_rate_and_parent; | ||
286 | } | ||
287 | |||
253 | if (gate_hw && gate_ops) { | 288 | if (gate_hw && gate_ops) { |
254 | if (!gate_ops->is_enabled || !gate_ops->enable || | 289 | if (!gate_ops->is_enabled || !gate_ops->enable || |
255 | !gate_ops->disable) { | 290 | !gate_ops->disable) { |
256 | clk = ERR_PTR(-EINVAL); | 291 | hw = ERR_PTR(-EINVAL); |
257 | goto err; | 292 | goto err; |
258 | } | 293 | } |
259 | 294 | ||
@@ -267,22 +302,56 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
267 | init.ops = clk_composite_ops; | 302 | init.ops = clk_composite_ops; |
268 | composite->hw.init = &init; | 303 | composite->hw.init = &init; |
269 | 304 | ||
270 | clk = clk_register(dev, &composite->hw); | 305 | ret = clk_hw_register(dev, hw); |
271 | if (IS_ERR(clk)) | 306 | if (ret) { |
307 | hw = ERR_PTR(ret); | ||
272 | goto err; | 308 | goto err; |
309 | } | ||
273 | 310 | ||
274 | if (composite->mux_hw) | 311 | if (composite->mux_hw) |
275 | composite->mux_hw->clk = clk; | 312 | composite->mux_hw->clk = hw->clk; |
276 | 313 | ||
277 | if (composite->rate_hw) | 314 | if (composite->rate_hw) |
278 | composite->rate_hw->clk = clk; | 315 | composite->rate_hw->clk = hw->clk; |
279 | 316 | ||
280 | if (composite->gate_hw) | 317 | if (composite->gate_hw) |
281 | composite->gate_hw->clk = clk; | 318 | composite->gate_hw->clk = hw->clk; |
282 | 319 | ||
283 | return clk; | 320 | return hw; |
284 | 321 | ||
285 | err: | 322 | err: |
286 | kfree(composite); | 323 | kfree(composite); |
287 | return clk; | 324 | return hw; |
325 | } | ||
326 | |||
327 | struct clk *clk_register_composite(struct device *dev, const char *name, | ||
328 | const char * const *parent_names, int num_parents, | ||
329 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
330 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, | ||
331 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
332 | unsigned long flags) | ||
333 | { | ||
334 | struct clk_hw *hw; | ||
335 | |||
336 | hw = clk_hw_register_composite(dev, name, parent_names, num_parents, | ||
337 | mux_hw, mux_ops, rate_hw, rate_ops, gate_hw, gate_ops, | ||
338 | flags); | ||
339 | if (IS_ERR(hw)) | ||
340 | return ERR_CAST(hw); | ||
341 | return hw->clk; | ||
342 | } | ||
343 | |||
344 | void clk_unregister_composite(struct clk *clk) | ||
345 | { | ||
346 | struct clk_composite *composite; | ||
347 | struct clk_hw *hw; | ||
348 | |||
349 | hw = __clk_get_hw(clk); | ||
350 | if (!hw) | ||
351 | return; | ||
352 | |||
353 | composite = to_clk_composite(hw); | ||
354 | |||
355 | clk_unregister(clk); | ||
356 | kfree(composite); | ||
288 | } | 357 | } |
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 00e035b51c69..a0f55bc1ad3d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
@@ -426,15 +426,16 @@ const struct clk_ops clk_divider_ro_ops = { | |||
426 | }; | 426 | }; |
427 | EXPORT_SYMBOL_GPL(clk_divider_ro_ops); | 427 | EXPORT_SYMBOL_GPL(clk_divider_ro_ops); |
428 | 428 | ||
429 | static struct clk *_register_divider(struct device *dev, const char *name, | 429 | static struct clk_hw *_register_divider(struct device *dev, const char *name, |
430 | const char *parent_name, unsigned long flags, | 430 | const char *parent_name, unsigned long flags, |
431 | void __iomem *reg, u8 shift, u8 width, | 431 | void __iomem *reg, u8 shift, u8 width, |
432 | u8 clk_divider_flags, const struct clk_div_table *table, | 432 | u8 clk_divider_flags, const struct clk_div_table *table, |
433 | spinlock_t *lock) | 433 | spinlock_t *lock) |
434 | { | 434 | { |
435 | struct clk_divider *div; | 435 | struct clk_divider *div; |
436 | struct clk *clk; | 436 | struct clk_hw *hw; |
437 | struct clk_init_data init; | 437 | struct clk_init_data init; |
438 | int ret; | ||
438 | 439 | ||
439 | if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { | 440 | if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { |
440 | if (width + shift > 16) { | 441 | if (width + shift > 16) { |
@@ -467,12 +468,14 @@ static struct clk *_register_divider(struct device *dev, const char *name, | |||
467 | div->table = table; | 468 | div->table = table; |
468 | 469 | ||
469 | /* register the clock */ | 470 | /* register the clock */ |
470 | clk = clk_register(dev, &div->hw); | 471 | hw = &div->hw; |
471 | 472 | ret = clk_hw_register(dev, hw); | |
472 | if (IS_ERR(clk)) | 473 | if (ret) { |
473 | kfree(div); | 474 | kfree(div); |
475 | hw = ERR_PTR(ret); | ||
476 | } | ||
474 | 477 | ||
475 | return clk; | 478 | return hw; |
476 | } | 479 | } |
477 | 480 | ||
478 | /** | 481 | /** |
@@ -492,12 +495,39 @@ struct clk *clk_register_divider(struct device *dev, const char *name, | |||
492 | void __iomem *reg, u8 shift, u8 width, | 495 | void __iomem *reg, u8 shift, u8 width, |
493 | u8 clk_divider_flags, spinlock_t *lock) | 496 | u8 clk_divider_flags, spinlock_t *lock) |
494 | { | 497 | { |
495 | return _register_divider(dev, name, parent_name, flags, reg, shift, | 498 | struct clk_hw *hw; |
499 | |||
500 | hw = _register_divider(dev, name, parent_name, flags, reg, shift, | ||
496 | width, clk_divider_flags, NULL, lock); | 501 | width, clk_divider_flags, NULL, lock); |
502 | if (IS_ERR(hw)) | ||
503 | return ERR_CAST(hw); | ||
504 | return hw->clk; | ||
497 | } | 505 | } |
498 | EXPORT_SYMBOL_GPL(clk_register_divider); | 506 | EXPORT_SYMBOL_GPL(clk_register_divider); |
499 | 507 | ||
500 | /** | 508 | /** |
509 | * clk_hw_register_divider - register a divider clock with the clock framework | ||
510 | * @dev: device registering this clock | ||
511 | * @name: name of this clock | ||
512 | * @parent_name: name of clock's parent | ||
513 | * @flags: framework-specific flags | ||
514 | * @reg: register address to adjust divider | ||
515 | * @shift: number of bits to shift the bitfield | ||
516 | * @width: width of the bitfield | ||
517 | * @clk_divider_flags: divider-specific flags for this clock | ||
518 | * @lock: shared register lock for this clock | ||
519 | */ | ||
520 | struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, | ||
521 | const char *parent_name, unsigned long flags, | ||
522 | void __iomem *reg, u8 shift, u8 width, | ||
523 | u8 clk_divider_flags, spinlock_t *lock) | ||
524 | { | ||
525 | return _register_divider(dev, name, parent_name, flags, reg, shift, | ||
526 | width, clk_divider_flags, NULL, lock); | ||
527 | } | ||
528 | EXPORT_SYMBOL_GPL(clk_hw_register_divider); | ||
529 | |||
530 | /** | ||
501 | * clk_register_divider_table - register a table based divider clock with | 531 | * clk_register_divider_table - register a table based divider clock with |
502 | * the clock framework | 532 | * the clock framework |
503 | * @dev: device registering this clock | 533 | * @dev: device registering this clock |
@@ -517,11 +547,41 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, | |||
517 | u8 clk_divider_flags, const struct clk_div_table *table, | 547 | u8 clk_divider_flags, const struct clk_div_table *table, |
518 | spinlock_t *lock) | 548 | spinlock_t *lock) |
519 | { | 549 | { |
520 | return _register_divider(dev, name, parent_name, flags, reg, shift, | 550 | struct clk_hw *hw; |
551 | |||
552 | hw = _register_divider(dev, name, parent_name, flags, reg, shift, | ||
521 | width, clk_divider_flags, table, lock); | 553 | width, clk_divider_flags, table, lock); |
554 | if (IS_ERR(hw)) | ||
555 | return ERR_CAST(hw); | ||
556 | return hw->clk; | ||
522 | } | 557 | } |
523 | EXPORT_SYMBOL_GPL(clk_register_divider_table); | 558 | EXPORT_SYMBOL_GPL(clk_register_divider_table); |
524 | 559 | ||
560 | /** | ||
561 | * clk_hw_register_divider_table - register a table based divider clock with | ||
562 | * the clock framework | ||
563 | * @dev: device registering this clock | ||
564 | * @name: name of this clock | ||
565 | * @parent_name: name of clock's parent | ||
566 | * @flags: framework-specific flags | ||
567 | * @reg: register address to adjust divider | ||
568 | * @shift: number of bits to shift the bitfield | ||
569 | * @width: width of the bitfield | ||
570 | * @clk_divider_flags: divider-specific flags for this clock | ||
571 | * @table: array of divider/value pairs ending with a div set to 0 | ||
572 | * @lock: shared register lock for this clock | ||
573 | */ | ||
574 | struct clk_hw *clk_hw_register_divider_table(struct device *dev, | ||
575 | const char *name, const char *parent_name, unsigned long flags, | ||
576 | void __iomem *reg, u8 shift, u8 width, | ||
577 | u8 clk_divider_flags, const struct clk_div_table *table, | ||
578 | spinlock_t *lock) | ||
579 | { | ||
580 | return _register_divider(dev, name, parent_name, flags, reg, shift, | ||
581 | width, clk_divider_flags, table, lock); | ||
582 | } | ||
583 | EXPORT_SYMBOL_GPL(clk_hw_register_divider_table); | ||
584 | |||
525 | void clk_unregister_divider(struct clk *clk) | 585 | void clk_unregister_divider(struct clk *clk) |
526 | { | 586 | { |
527 | struct clk_divider *div; | 587 | struct clk_divider *div; |
@@ -537,3 +597,18 @@ void clk_unregister_divider(struct clk *clk) | |||
537 | kfree(div); | 597 | kfree(div); |
538 | } | 598 | } |
539 | EXPORT_SYMBOL_GPL(clk_unregister_divider); | 599 | EXPORT_SYMBOL_GPL(clk_unregister_divider); |
600 | |||
601 | /** | ||
602 | * clk_hw_unregister_divider - unregister a clk divider | ||
603 | * @hw: hardware-specific clock data to unregister | ||
604 | */ | ||
605 | void clk_hw_unregister_divider(struct clk_hw *hw) | ||
606 | { | ||
607 | struct clk_divider *div; | ||
608 | |||
609 | div = to_clk_divider(hw); | ||
610 | |||
611 | clk_hw_unregister(hw); | ||
612 | kfree(div); | ||
613 | } | ||
614 | EXPORT_SYMBOL_GPL(clk_hw_unregister_divider); | ||
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 053448e2453d..75cd6c792cb8 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c | |||
@@ -68,13 +68,14 @@ const struct clk_ops clk_fixed_factor_ops = { | |||
68 | }; | 68 | }; |
69 | EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); | 69 | EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); |
70 | 70 | ||
71 | struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | 71 | struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, |
72 | const char *parent_name, unsigned long flags, | 72 | const char *name, const char *parent_name, unsigned long flags, |
73 | unsigned int mult, unsigned int div) | 73 | unsigned int mult, unsigned int div) |
74 | { | 74 | { |
75 | struct clk_fixed_factor *fix; | 75 | struct clk_fixed_factor *fix; |
76 | struct clk_init_data init; | 76 | struct clk_init_data init; |
77 | struct clk *clk; | 77 | struct clk_hw *hw; |
78 | int ret; | ||
78 | 79 | ||
79 | fix = kmalloc(sizeof(*fix), GFP_KERNEL); | 80 | fix = kmalloc(sizeof(*fix), GFP_KERNEL); |
80 | if (!fix) | 81 | if (!fix) |
@@ -91,12 +92,28 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | |||
91 | init.parent_names = &parent_name; | 92 | init.parent_names = &parent_name; |
92 | init.num_parents = 1; | 93 | init.num_parents = 1; |
93 | 94 | ||
94 | clk = clk_register(dev, &fix->hw); | 95 | hw = &fix->hw; |
95 | 96 | ret = clk_hw_register(dev, hw); | |
96 | if (IS_ERR(clk)) | 97 | if (ret) { |
97 | kfree(fix); | 98 | kfree(fix); |
99 | hw = ERR_PTR(ret); | ||
100 | } | ||
101 | |||
102 | return hw; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor); | ||
105 | |||
106 | struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | ||
107 | const char *parent_name, unsigned long flags, | ||
108 | unsigned int mult, unsigned int div) | ||
109 | { | ||
110 | struct clk_hw *hw; | ||
98 | 111 | ||
99 | return clk; | 112 | hw = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult, |
113 | div); | ||
114 | if (IS_ERR(hw)) | ||
115 | return ERR_CAST(hw); | ||
116 | return hw->clk; | ||
100 | } | 117 | } |
101 | EXPORT_SYMBOL_GPL(clk_register_fixed_factor); | 118 | EXPORT_SYMBOL_GPL(clk_register_fixed_factor); |
102 | 119 | ||
@@ -113,6 +130,17 @@ void clk_unregister_fixed_factor(struct clk *clk) | |||
113 | } | 130 | } |
114 | EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor); | 131 | EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor); |
115 | 132 | ||
133 | void clk_hw_unregister_fixed_factor(struct clk_hw *hw) | ||
134 | { | ||
135 | struct clk_fixed_factor *fix; | ||
136 | |||
137 | fix = to_clk_fixed_factor(hw); | ||
138 | |||
139 | clk_hw_unregister(hw); | ||
140 | kfree(fix); | ||
141 | } | ||
142 | EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor); | ||
143 | |||
116 | #ifdef CONFIG_OF | 144 | #ifdef CONFIG_OF |
117 | /** | 145 | /** |
118 | * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock | 146 | * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock |
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index cd9dc925b3f8..8e4453eb54e8 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c | |||
@@ -45,8 +45,8 @@ const struct clk_ops clk_fixed_rate_ops = { | |||
45 | EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); | 45 | EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the | 48 | * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with |
49 | * clock framework | 49 | * the clock framework |
50 | * @dev: device that is registering this clock | 50 | * @dev: device that is registering this clock |
51 | * @name: name of this clock | 51 | * @name: name of this clock |
52 | * @parent_name: name of clock's parent | 52 | * @parent_name: name of clock's parent |
@@ -54,13 +54,14 @@ EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); | |||
54 | * @fixed_rate: non-adjustable clock rate | 54 | * @fixed_rate: non-adjustable clock rate |
55 | * @fixed_accuracy: non-adjustable clock rate | 55 | * @fixed_accuracy: non-adjustable clock rate |
56 | */ | 56 | */ |
57 | struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, | 57 | struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, |
58 | const char *name, const char *parent_name, unsigned long flags, | 58 | const char *name, const char *parent_name, unsigned long flags, |
59 | unsigned long fixed_rate, unsigned long fixed_accuracy) | 59 | unsigned long fixed_rate, unsigned long fixed_accuracy) |
60 | { | 60 | { |
61 | struct clk_fixed_rate *fixed; | 61 | struct clk_fixed_rate *fixed; |
62 | struct clk *clk; | 62 | struct clk_hw *hw; |
63 | struct clk_init_data init; | 63 | struct clk_init_data init; |
64 | int ret; | ||
64 | 65 | ||
65 | /* allocate fixed-rate clock */ | 66 | /* allocate fixed-rate clock */ |
66 | fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); | 67 | fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); |
@@ -79,22 +80,49 @@ struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, | |||
79 | fixed->hw.init = &init; | 80 | fixed->hw.init = &init; |
80 | 81 | ||
81 | /* register the clock */ | 82 | /* register the clock */ |
82 | clk = clk_register(dev, &fixed->hw); | 83 | hw = &fixed->hw; |
83 | if (IS_ERR(clk)) | 84 | ret = clk_hw_register(dev, hw); |
85 | if (ret) { | ||
84 | kfree(fixed); | 86 | kfree(fixed); |
87 | hw = ERR_PTR(ret); | ||
88 | } | ||
85 | 89 | ||
86 | return clk; | 90 | return hw; |
91 | } | ||
92 | EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy); | ||
93 | |||
94 | struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, | ||
95 | const char *name, const char *parent_name, unsigned long flags, | ||
96 | unsigned long fixed_rate, unsigned long fixed_accuracy) | ||
97 | { | ||
98 | struct clk_hw *hw; | ||
99 | |||
100 | hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, | ||
101 | flags, fixed_rate, fixed_accuracy); | ||
102 | if (IS_ERR(hw)) | ||
103 | return ERR_CAST(hw); | ||
104 | return hw->clk; | ||
87 | } | 105 | } |
88 | EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy); | 106 | EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy); |
89 | 107 | ||
90 | /** | 108 | /** |
91 | * clk_register_fixed_rate - register fixed-rate clock with the clock framework | 109 | * clk_hw_register_fixed_rate - register fixed-rate clock with the clock |
110 | * framework | ||
92 | * @dev: device that is registering this clock | 111 | * @dev: device that is registering this clock |
93 | * @name: name of this clock | 112 | * @name: name of this clock |
94 | * @parent_name: name of clock's parent | 113 | * @parent_name: name of clock's parent |
95 | * @flags: framework-specific flags | 114 | * @flags: framework-specific flags |
96 | * @fixed_rate: non-adjustable clock rate | 115 | * @fixed_rate: non-adjustable clock rate |
97 | */ | 116 | */ |
117 | struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name, | ||
118 | const char *parent_name, unsigned long flags, | ||
119 | unsigned long fixed_rate) | ||
120 | { | ||
121 | return clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, | ||
122 | flags, fixed_rate, 0); | ||
123 | } | ||
124 | EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate); | ||
125 | |||
98 | struct clk *clk_register_fixed_rate(struct device *dev, const char *name, | 126 | struct clk *clk_register_fixed_rate(struct device *dev, const char *name, |
99 | const char *parent_name, unsigned long flags, | 127 | const char *parent_name, unsigned long flags, |
100 | unsigned long fixed_rate) | 128 | unsigned long fixed_rate) |
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index 1abcd76b4993..aab904618eb6 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c | |||
@@ -116,14 +116,15 @@ const struct clk_ops clk_fractional_divider_ops = { | |||
116 | }; | 116 | }; |
117 | EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); | 117 | EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); |
118 | 118 | ||
119 | struct clk *clk_register_fractional_divider(struct device *dev, | 119 | struct clk_hw *clk_hw_register_fractional_divider(struct device *dev, |
120 | const char *name, const char *parent_name, unsigned long flags, | 120 | const char *name, const char *parent_name, unsigned long flags, |
121 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, | 121 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, |
122 | u8 clk_divider_flags, spinlock_t *lock) | 122 | u8 clk_divider_flags, spinlock_t *lock) |
123 | { | 123 | { |
124 | struct clk_fractional_divider *fd; | 124 | struct clk_fractional_divider *fd; |
125 | struct clk_init_data init; | 125 | struct clk_init_data init; |
126 | struct clk *clk; | 126 | struct clk_hw *hw; |
127 | int ret; | ||
127 | 128 | ||
128 | fd = kzalloc(sizeof(*fd), GFP_KERNEL); | 129 | fd = kzalloc(sizeof(*fd), GFP_KERNEL); |
129 | if (!fd) | 130 | if (!fd) |
@@ -146,10 +147,39 @@ struct clk *clk_register_fractional_divider(struct device *dev, | |||
146 | fd->lock = lock; | 147 | fd->lock = lock; |
147 | fd->hw.init = &init; | 148 | fd->hw.init = &init; |
148 | 149 | ||
149 | clk = clk_register(dev, &fd->hw); | 150 | hw = &fd->hw; |
150 | if (IS_ERR(clk)) | 151 | ret = clk_hw_register(dev, hw); |
152 | if (ret) { | ||
151 | kfree(fd); | 153 | kfree(fd); |
154 | hw = ERR_PTR(ret); | ||
155 | } | ||
156 | |||
157 | return hw; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider); | ||
152 | 160 | ||
153 | return clk; | 161 | struct clk *clk_register_fractional_divider(struct device *dev, |
162 | const char *name, const char *parent_name, unsigned long flags, | ||
163 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, | ||
164 | u8 clk_divider_flags, spinlock_t *lock) | ||
165 | { | ||
166 | struct clk_hw *hw; | ||
167 | |||
168 | hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags, | ||
169 | reg, mshift, mwidth, nshift, nwidth, clk_divider_flags, | ||
170 | lock); | ||
171 | if (IS_ERR(hw)) | ||
172 | return ERR_CAST(hw); | ||
173 | return hw->clk; | ||
154 | } | 174 | } |
155 | EXPORT_SYMBOL_GPL(clk_register_fractional_divider); | 175 | EXPORT_SYMBOL_GPL(clk_register_fractional_divider); |
176 | |||
177 | void clk_hw_unregister_fractional_divider(struct clk_hw *hw) | ||
178 | { | ||
179 | struct clk_fractional_divider *fd; | ||
180 | |||
181 | fd = to_clk_fd(hw); | ||
182 | |||
183 | clk_hw_unregister(hw); | ||
184 | kfree(fd); | ||
185 | } | ||
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index d0d8ec8e1f1b..4e691e35483a 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c | |||
@@ -110,7 +110,7 @@ const struct clk_ops clk_gate_ops = { | |||
110 | EXPORT_SYMBOL_GPL(clk_gate_ops); | 110 | EXPORT_SYMBOL_GPL(clk_gate_ops); |
111 | 111 | ||
112 | /** | 112 | /** |
113 | * clk_register_gate - register a gate clock with the clock framework | 113 | * clk_hw_register_gate - register a gate clock with the clock framework |
114 | * @dev: device that is registering this clock | 114 | * @dev: device that is registering this clock |
115 | * @name: name of this clock | 115 | * @name: name of this clock |
116 | * @parent_name: name of this clock's parent | 116 | * @parent_name: name of this clock's parent |
@@ -120,14 +120,15 @@ EXPORT_SYMBOL_GPL(clk_gate_ops); | |||
120 | * @clk_gate_flags: gate-specific flags for this clock | 120 | * @clk_gate_flags: gate-specific flags for this clock |
121 | * @lock: shared register lock for this clock | 121 | * @lock: shared register lock for this clock |
122 | */ | 122 | */ |
123 | struct clk *clk_register_gate(struct device *dev, const char *name, | 123 | struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, |
124 | const char *parent_name, unsigned long flags, | 124 | const char *parent_name, unsigned long flags, |
125 | void __iomem *reg, u8 bit_idx, | 125 | void __iomem *reg, u8 bit_idx, |
126 | u8 clk_gate_flags, spinlock_t *lock) | 126 | u8 clk_gate_flags, spinlock_t *lock) |
127 | { | 127 | { |
128 | struct clk_gate *gate; | 128 | struct clk_gate *gate; |
129 | struct clk *clk; | 129 | struct clk_hw *hw; |
130 | struct clk_init_data init; | 130 | struct clk_init_data init; |
131 | int ret; | ||
131 | 132 | ||
132 | if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { | 133 | if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { |
133 | if (bit_idx > 15) { | 134 | if (bit_idx > 15) { |
@@ -154,12 +155,29 @@ struct clk *clk_register_gate(struct device *dev, const char *name, | |||
154 | gate->lock = lock; | 155 | gate->lock = lock; |
155 | gate->hw.init = &init; | 156 | gate->hw.init = &init; |
156 | 157 | ||
157 | clk = clk_register(dev, &gate->hw); | 158 | hw = &gate->hw; |
158 | 159 | ret = clk_hw_register(dev, hw); | |
159 | if (IS_ERR(clk)) | 160 | if (ret) { |
160 | kfree(gate); | 161 | kfree(gate); |
162 | hw = ERR_PTR(ret); | ||
163 | } | ||
161 | 164 | ||
162 | return clk; | 165 | return hw; |
166 | } | ||
167 | EXPORT_SYMBOL_GPL(clk_hw_register_gate); | ||
168 | |||
169 | struct clk *clk_register_gate(struct device *dev, const char *name, | ||
170 | const char *parent_name, unsigned long flags, | ||
171 | void __iomem *reg, u8 bit_idx, | ||
172 | u8 clk_gate_flags, spinlock_t *lock) | ||
173 | { | ||
174 | struct clk_hw *hw; | ||
175 | |||
176 | hw = clk_hw_register_gate(dev, name, parent_name, flags, reg, | ||
177 | bit_idx, clk_gate_flags, lock); | ||
178 | if (IS_ERR(hw)) | ||
179 | return ERR_CAST(hw); | ||
180 | return hw->clk; | ||
163 | } | 181 | } |
164 | EXPORT_SYMBOL_GPL(clk_register_gate); | 182 | EXPORT_SYMBOL_GPL(clk_register_gate); |
165 | 183 | ||
@@ -178,3 +196,14 @@ void clk_unregister_gate(struct clk *clk) | |||
178 | kfree(gate); | 196 | kfree(gate); |
179 | } | 197 | } |
180 | EXPORT_SYMBOL_GPL(clk_unregister_gate); | 198 | EXPORT_SYMBOL_GPL(clk_unregister_gate); |
199 | |||
200 | void clk_hw_unregister_gate(struct clk_hw *hw) | ||
201 | { | ||
202 | struct clk_gate *gate; | ||
203 | |||
204 | gate = to_clk_gate(hw); | ||
205 | |||
206 | clk_hw_unregister(hw); | ||
207 | kfree(gate); | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(clk_hw_unregister_gate); | ||
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 08f65acc5d57..86b245746a6b 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c | |||
@@ -94,13 +94,13 @@ const struct clk_ops clk_gpio_mux_ops = { | |||
94 | }; | 94 | }; |
95 | EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); | 95 | EXPORT_SYMBOL_GPL(clk_gpio_mux_ops); |
96 | 96 | ||
97 | static struct clk *clk_register_gpio(struct device *dev, const char *name, | 97 | static struct clk_hw *clk_register_gpio(struct device *dev, const char *name, |
98 | const char * const *parent_names, u8 num_parents, unsigned gpio, | 98 | const char * const *parent_names, u8 num_parents, unsigned gpio, |
99 | bool active_low, unsigned long flags, | 99 | bool active_low, unsigned long flags, |
100 | const struct clk_ops *clk_gpio_ops) | 100 | const struct clk_ops *clk_gpio_ops) |
101 | { | 101 | { |
102 | struct clk_gpio *clk_gpio; | 102 | struct clk_gpio *clk_gpio; |
103 | struct clk *clk; | 103 | struct clk_hw *hw; |
104 | struct clk_init_data init = {}; | 104 | struct clk_init_data init = {}; |
105 | unsigned long gpio_flags; | 105 | unsigned long gpio_flags; |
106 | int err; | 106 | int err; |
@@ -141,24 +141,26 @@ static struct clk *clk_register_gpio(struct device *dev, const char *name, | |||
141 | clk_gpio->gpiod = gpio_to_desc(gpio); | 141 | clk_gpio->gpiod = gpio_to_desc(gpio); |
142 | clk_gpio->hw.init = &init; | 142 | clk_gpio->hw.init = &init; |
143 | 143 | ||
144 | hw = &clk_gpio->hw; | ||
144 | if (dev) | 145 | if (dev) |
145 | clk = devm_clk_register(dev, &clk_gpio->hw); | 146 | err = devm_clk_hw_register(dev, hw); |
146 | else | 147 | else |
147 | clk = clk_register(NULL, &clk_gpio->hw); | 148 | err = clk_hw_register(NULL, hw); |
148 | 149 | ||
149 | if (!IS_ERR(clk)) | 150 | if (!err) |
150 | return clk; | 151 | return hw; |
151 | 152 | ||
152 | if (!dev) { | 153 | if (!dev) { |
153 | gpiod_put(clk_gpio->gpiod); | 154 | gpiod_put(clk_gpio->gpiod); |
154 | kfree(clk_gpio); | 155 | kfree(clk_gpio); |
155 | } | 156 | } |
156 | 157 | ||
157 | return clk; | 158 | return ERR_PTR(err); |
158 | } | 159 | } |
159 | 160 | ||
160 | /** | 161 | /** |
161 | * clk_register_gpio_gate - register a gpio clock gate with the clock framework | 162 | * clk_hw_register_gpio_gate - register a gpio clock gate with the clock |
163 | * framework | ||
162 | * @dev: device that is registering this clock | 164 | * @dev: device that is registering this clock |
163 | * @name: name of this clock | 165 | * @name: name of this clock |
164 | * @parent_name: name of this clock's parent | 166 | * @parent_name: name of this clock's parent |
@@ -166,7 +168,7 @@ static struct clk *clk_register_gpio(struct device *dev, const char *name, | |||
166 | * @active_low: true if gpio should be set to 0 to enable clock | 168 | * @active_low: true if gpio should be set to 0 to enable clock |
167 | * @flags: clock flags | 169 | * @flags: clock flags |
168 | */ | 170 | */ |
169 | struct clk *clk_register_gpio_gate(struct device *dev, const char *name, | 171 | struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, |
170 | const char *parent_name, unsigned gpio, bool active_low, | 172 | const char *parent_name, unsigned gpio, bool active_low, |
171 | unsigned long flags) | 173 | unsigned long flags) |
172 | { | 174 | { |
@@ -175,10 +177,24 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name, | |||
175 | (parent_name ? 1 : 0), gpio, active_low, flags, | 177 | (parent_name ? 1 : 0), gpio, active_low, flags, |
176 | &clk_gpio_gate_ops); | 178 | &clk_gpio_gate_ops); |
177 | } | 179 | } |
180 | EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate); | ||
181 | |||
182 | struct clk *clk_register_gpio_gate(struct device *dev, const char *name, | ||
183 | const char *parent_name, unsigned gpio, bool active_low, | ||
184 | unsigned long flags) | ||
185 | { | ||
186 | struct clk_hw *hw; | ||
187 | |||
188 | hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low, | ||
189 | flags); | ||
190 | if (IS_ERR(hw)) | ||
191 | return ERR_CAST(hw); | ||
192 | return hw->clk; | ||
193 | } | ||
178 | EXPORT_SYMBOL_GPL(clk_register_gpio_gate); | 194 | EXPORT_SYMBOL_GPL(clk_register_gpio_gate); |
179 | 195 | ||
180 | /** | 196 | /** |
181 | * clk_register_gpio_mux - register a gpio clock mux with the clock framework | 197 | * clk_hw_register_gpio_mux - register a gpio clock mux with the clock framework |
182 | * @dev: device that is registering this clock | 198 | * @dev: device that is registering this clock |
183 | * @name: name of this clock | 199 | * @name: name of this clock |
184 | * @parent_names: names of this clock's parents | 200 | * @parent_names: names of this clock's parents |
@@ -187,7 +203,7 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate); | |||
187 | * @active_low: true if gpio should be set to 0 to enable clock | 203 | * @active_low: true if gpio should be set to 0 to enable clock |
188 | * @flags: clock flags | 204 | * @flags: clock flags |
189 | */ | 205 | */ |
190 | struct clk *clk_register_gpio_mux(struct device *dev, const char *name, | 206 | struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, |
191 | const char * const *parent_names, u8 num_parents, unsigned gpio, | 207 | const char * const *parent_names, u8 num_parents, unsigned gpio, |
192 | bool active_low, unsigned long flags) | 208 | bool active_low, unsigned long flags) |
193 | { | 209 | { |
@@ -199,6 +215,20 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, | |||
199 | return clk_register_gpio(dev, name, parent_names, num_parents, | 215 | return clk_register_gpio(dev, name, parent_names, num_parents, |
200 | gpio, active_low, flags, &clk_gpio_mux_ops); | 216 | gpio, active_low, flags, &clk_gpio_mux_ops); |
201 | } | 217 | } |
218 | EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux); | ||
219 | |||
220 | struct clk *clk_register_gpio_mux(struct device *dev, const char *name, | ||
221 | const char * const *parent_names, u8 num_parents, unsigned gpio, | ||
222 | bool active_low, unsigned long flags) | ||
223 | { | ||
224 | struct clk_hw *hw; | ||
225 | |||
226 | hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents, | ||
227 | gpio, active_low, flags); | ||
228 | if (IS_ERR(hw)) | ||
229 | return ERR_CAST(hw); | ||
230 | return hw->clk; | ||
231 | } | ||
202 | EXPORT_SYMBOL_GPL(clk_register_gpio_mux); | 232 | EXPORT_SYMBOL_GPL(clk_register_gpio_mux); |
203 | 233 | ||
204 | static int gpio_clk_driver_probe(struct platform_device *pdev) | 234 | static int gpio_clk_driver_probe(struct platform_device *pdev) |
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c index d4c61985f448..5097831387ff 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/clk-ls1x.c | |||
@@ -88,8 +88,7 @@ void __init ls1x_clk_init(void) | |||
88 | { | 88 | { |
89 | struct clk *clk; | 89 | struct clk *clk; |
90 | 90 | ||
91 | clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT, | 91 | clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC); |
92 | OSC); | ||
93 | clk_register_clkdev(clk, "osc_33m_clk", NULL); | 92 | clk_register_clkdev(clk, "osc_33m_clk", NULL); |
94 | 93 | ||
95 | /* clock derived from 33 MHz OSC clk */ | 94 | /* clock derived from 33 MHz OSC clk */ |
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 252188fd8bcd..16a3d5717f4e 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
@@ -113,16 +113,17 @@ const struct clk_ops clk_mux_ro_ops = { | |||
113 | }; | 113 | }; |
114 | EXPORT_SYMBOL_GPL(clk_mux_ro_ops); | 114 | EXPORT_SYMBOL_GPL(clk_mux_ro_ops); |
115 | 115 | ||
116 | struct clk *clk_register_mux_table(struct device *dev, const char *name, | 116 | struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, |
117 | const char * const *parent_names, u8 num_parents, | 117 | const char * const *parent_names, u8 num_parents, |
118 | unsigned long flags, | 118 | unsigned long flags, |
119 | void __iomem *reg, u8 shift, u32 mask, | 119 | void __iomem *reg, u8 shift, u32 mask, |
120 | u8 clk_mux_flags, u32 *table, spinlock_t *lock) | 120 | u8 clk_mux_flags, u32 *table, spinlock_t *lock) |
121 | { | 121 | { |
122 | struct clk_mux *mux; | 122 | struct clk_mux *mux; |
123 | struct clk *clk; | 123 | struct clk_hw *hw; |
124 | struct clk_init_data init; | 124 | struct clk_init_data init; |
125 | u8 width = 0; | 125 | u8 width = 0; |
126 | int ret; | ||
126 | 127 | ||
127 | if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { | 128 | if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { |
128 | width = fls(mask) - ffs(mask) + 1; | 129 | width = fls(mask) - ffs(mask) + 1; |
@@ -157,12 +158,31 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, | |||
157 | mux->table = table; | 158 | mux->table = table; |
158 | mux->hw.init = &init; | 159 | mux->hw.init = &init; |
159 | 160 | ||
160 | clk = clk_register(dev, &mux->hw); | 161 | hw = &mux->hw; |
161 | 162 | ret = clk_hw_register(dev, hw); | |
162 | if (IS_ERR(clk)) | 163 | if (ret) { |
163 | kfree(mux); | 164 | kfree(mux); |
165 | hw = ERR_PTR(ret); | ||
166 | } | ||
164 | 167 | ||
165 | return clk; | 168 | return hw; |
169 | } | ||
170 | EXPORT_SYMBOL_GPL(clk_hw_register_mux_table); | ||
171 | |||
172 | struct clk *clk_register_mux_table(struct device *dev, const char *name, | ||
173 | const char * const *parent_names, u8 num_parents, | ||
174 | unsigned long flags, | ||
175 | void __iomem *reg, u8 shift, u32 mask, | ||
176 | u8 clk_mux_flags, u32 *table, spinlock_t *lock) | ||
177 | { | ||
178 | struct clk_hw *hw; | ||
179 | |||
180 | hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents, | ||
181 | flags, reg, shift, mask, clk_mux_flags, | ||
182 | table, lock); | ||
183 | if (IS_ERR(hw)) | ||
184 | return ERR_CAST(hw); | ||
185 | return hw->clk; | ||
166 | } | 186 | } |
167 | EXPORT_SYMBOL_GPL(clk_register_mux_table); | 187 | EXPORT_SYMBOL_GPL(clk_register_mux_table); |
168 | 188 | ||
@@ -180,6 +200,20 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
180 | } | 200 | } |
181 | EXPORT_SYMBOL_GPL(clk_register_mux); | 201 | EXPORT_SYMBOL_GPL(clk_register_mux); |
182 | 202 | ||
203 | struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, | ||
204 | const char * const *parent_names, u8 num_parents, | ||
205 | unsigned long flags, | ||
206 | void __iomem *reg, u8 shift, u8 width, | ||
207 | u8 clk_mux_flags, spinlock_t *lock) | ||
208 | { | ||
209 | u32 mask = BIT(width) - 1; | ||
210 | |||
211 | return clk_hw_register_mux_table(dev, name, parent_names, num_parents, | ||
212 | flags, reg, shift, mask, clk_mux_flags, | ||
213 | NULL, lock); | ||
214 | } | ||
215 | EXPORT_SYMBOL_GPL(clk_hw_register_mux); | ||
216 | |||
183 | void clk_unregister_mux(struct clk *clk) | 217 | void clk_unregister_mux(struct clk *clk) |
184 | { | 218 | { |
185 | struct clk_mux *mux; | 219 | struct clk_mux *mux; |
@@ -195,3 +229,14 @@ void clk_unregister_mux(struct clk *clk) | |||
195 | kfree(mux); | 229 | kfree(mux); |
196 | } | 230 | } |
197 | EXPORT_SYMBOL_GPL(clk_unregister_mux); | 231 | EXPORT_SYMBOL_GPL(clk_unregister_mux); |
232 | |||
233 | void clk_hw_unregister_mux(struct clk_hw *hw) | ||
234 | { | ||
235 | struct clk_mux *mux; | ||
236 | |||
237 | mux = to_clk_mux(hw); | ||
238 | |||
239 | clk_hw_unregister(hw); | ||
240 | kfree(mux); | ||
241 | } | ||
242 | EXPORT_SYMBOL_GPL(clk_hw_unregister_mux); | ||
diff --git a/drivers/clk/clk-nspire.c b/drivers/clk/clk-nspire.c index a378db7b2382..64f196a90816 100644 --- a/drivers/clk/clk-nspire.c +++ b/drivers/clk/clk-nspire.c | |||
@@ -125,8 +125,7 @@ static void __init nspire_clk_setup(struct device_node *node, | |||
125 | 125 | ||
126 | of_property_read_string(node, "clock-output-names", &clk_name); | 126 | of_property_read_string(node, "clock-output-names", &clk_name); |
127 | 127 | ||
128 | clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, | 128 | clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, info.base_clock); |
129 | info.base_clock); | ||
130 | if (!IS_ERR(clk)) | 129 | if (!IS_ERR(clk)) |
131 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | 130 | of_clk_add_provider(node, of_clk_src_simple_get, clk); |
132 | else | 131 | else |
diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c new file mode 100644 index 000000000000..efba7d4dbcfc --- /dev/null +++ b/drivers/clk/clk-oxnas.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Broadcom | ||
3 | * Copyright (C) 2012 Stephen Warren | ||
4 | * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk-provider.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/stringify.h> | ||
25 | #include <linux/regmap.h> | ||
26 | #include <linux/mfd/syscon.h> | ||
27 | |||
28 | /* Standard regmap gate clocks */ | ||
29 | struct clk_oxnas { | ||
30 | struct clk_hw hw; | ||
31 | signed char bit; | ||
32 | struct regmap *regmap; | ||
33 | }; | ||
34 | |||
35 | /* Regmap offsets */ | ||
36 | #define CLK_STAT_REGOFFSET 0x24 | ||
37 | #define CLK_SET_REGOFFSET 0x2c | ||
38 | #define CLK_CLR_REGOFFSET 0x30 | ||
39 | |||
40 | static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw) | ||
41 | { | ||
42 | return container_of(hw, struct clk_oxnas, hw); | ||
43 | } | ||
44 | |||
45 | static int oxnas_clk_is_enabled(struct clk_hw *hw) | ||
46 | { | ||
47 | struct clk_oxnas *std = to_clk_oxnas(hw); | ||
48 | int ret; | ||
49 | unsigned int val; | ||
50 | |||
51 | ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | |||
55 | return val & BIT(std->bit); | ||
56 | } | ||
57 | |||
58 | static int oxnas_clk_enable(struct clk_hw *hw) | ||
59 | { | ||
60 | struct clk_oxnas *std = to_clk_oxnas(hw); | ||
61 | |||
62 | regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit)); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static void oxnas_clk_disable(struct clk_hw *hw) | ||
68 | { | ||
69 | struct clk_oxnas *std = to_clk_oxnas(hw); | ||
70 | |||
71 | regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit)); | ||
72 | } | ||
73 | |||
74 | static const struct clk_ops oxnas_clk_ops = { | ||
75 | .enable = oxnas_clk_enable, | ||
76 | .disable = oxnas_clk_disable, | ||
77 | .is_enabled = oxnas_clk_is_enabled, | ||
78 | }; | ||
79 | |||
80 | static const char *const oxnas_clk_parents[] = { | ||
81 | "oscillator", | ||
82 | }; | ||
83 | |||
84 | static const char *const eth_parents[] = { | ||
85 | "gmacclk", | ||
86 | }; | ||
87 | |||
88 | #define DECLARE_STD_CLKP(__clk, __parent) \ | ||
89 | static const struct clk_init_data clk_##__clk##_init = { \ | ||
90 | .name = __stringify(__clk), \ | ||
91 | .ops = &oxnas_clk_ops, \ | ||
92 | .parent_names = __parent, \ | ||
93 | .num_parents = ARRAY_SIZE(__parent), \ | ||
94 | } | ||
95 | |||
96 | #define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents) | ||
97 | |||
98 | /* Hardware Bit - Clock association */ | ||
99 | struct clk_oxnas_init_data { | ||
100 | unsigned long bit; | ||
101 | const struct clk_init_data *clk_init; | ||
102 | }; | ||
103 | |||
104 | /* Clk init data declaration */ | ||
105 | DECLARE_STD_CLK(leon); | ||
106 | DECLARE_STD_CLK(dma_sgdma); | ||
107 | DECLARE_STD_CLK(cipher); | ||
108 | DECLARE_STD_CLK(sata); | ||
109 | DECLARE_STD_CLK(audio); | ||
110 | DECLARE_STD_CLK(usbmph); | ||
111 | DECLARE_STD_CLKP(etha, eth_parents); | ||
112 | DECLARE_STD_CLK(pciea); | ||
113 | DECLARE_STD_CLK(nand); | ||
114 | |||
115 | /* Table index is clock indice */ | ||
116 | static const struct clk_oxnas_init_data clk_oxnas_init[] = { | ||
117 | [0] = {0, &clk_leon_init}, | ||
118 | [1] = {1, &clk_dma_sgdma_init}, | ||
119 | [2] = {2, &clk_cipher_init}, | ||
120 | /* Skip & Do not touch to DDR clock */ | ||
121 | [3] = {4, &clk_sata_init}, | ||
122 | [4] = {5, &clk_audio_init}, | ||
123 | [5] = {6, &clk_usbmph_init}, | ||
124 | [6] = {7, &clk_etha_init}, | ||
125 | [7] = {8, &clk_pciea_init}, | ||
126 | [8] = {9, &clk_nand_init}, | ||
127 | }; | ||
128 | |||
129 | struct clk_oxnas_data { | ||
130 | struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)]; | ||
131 | struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)]; | ||
132 | struct clk *clks[ARRAY_SIZE(clk_oxnas_init)]; | ||
133 | }; | ||
134 | |||
135 | static int oxnas_stdclk_probe(struct platform_device *pdev) | ||
136 | { | ||
137 | struct device_node *np = pdev->dev.of_node; | ||
138 | struct clk_oxnas_data *clk_oxnas; | ||
139 | struct regmap *regmap; | ||
140 | int i; | ||
141 | |||
142 | clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL); | ||
143 | if (!clk_oxnas) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | regmap = syscon_node_to_regmap(of_get_parent(np)); | ||
147 | if (!regmap) { | ||
148 | dev_err(&pdev->dev, "failed to have parent regmap\n"); | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | |||
152 | for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) { | ||
153 | struct clk_oxnas *_clk; | ||
154 | |||
155 | _clk = &clk_oxnas->clk_oxnas[i]; | ||
156 | _clk->bit = clk_oxnas_init[i].bit; | ||
157 | _clk->hw.init = clk_oxnas_init[i].clk_init; | ||
158 | _clk->regmap = regmap; | ||
159 | |||
160 | clk_oxnas->clks[i] = | ||
161 | devm_clk_register(&pdev->dev, &_clk->hw); | ||
162 | if (WARN_ON(IS_ERR(clk_oxnas->clks[i]))) | ||
163 | return PTR_ERR(clk_oxnas->clks[i]); | ||
164 | } | ||
165 | |||
166 | clk_oxnas->onecell_data->clks = clk_oxnas->clks; | ||
167 | clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init); | ||
168 | |||
169 | return of_clk_add_provider(np, of_clk_src_onecell_get, | ||
170 | clk_oxnas->onecell_data); | ||
171 | } | ||
172 | |||
173 | static int oxnas_stdclk_remove(struct platform_device *pdev) | ||
174 | { | ||
175 | of_clk_del_provider(pdev->dev.of_node); | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static const struct of_device_id oxnas_stdclk_dt_ids[] = { | ||
181 | { .compatible = "oxsemi,ox810se-stdclk" }, | ||
182 | { } | ||
183 | }; | ||
184 | MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids); | ||
185 | |||
186 | static struct platform_driver oxnas_stdclk_driver = { | ||
187 | .probe = oxnas_stdclk_probe, | ||
188 | .remove = oxnas_stdclk_remove, | ||
189 | .driver = { | ||
190 | .name = "oxnas-stdclk", | ||
191 | .of_match_table = oxnas_stdclk_dt_ids, | ||
192 | }, | ||
193 | }; | ||
194 | |||
195 | module_platform_driver(oxnas_stdclk_driver); | ||
diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c index 9c0b8e6b1ab3..8328863cb0e0 100644 --- a/drivers/clk/clk-palmas.c +++ b/drivers/clk/clk-palmas.c | |||
@@ -132,7 +132,7 @@ static const struct palmas_clks_of_match_data palmas_of_clk32kg = { | |||
132 | .init = { | 132 | .init = { |
133 | .name = "clk32kg", | 133 | .name = "clk32kg", |
134 | .ops = &palmas_clks_ops, | 134 | .ops = &palmas_clks_ops, |
135 | .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, | 135 | .flags = CLK_IGNORE_UNUSED, |
136 | }, | 136 | }, |
137 | .desc = { | 137 | .desc = { |
138 | .clk_name = "clk32kg", | 138 | .clk_name = "clk32kg", |
@@ -148,7 +148,7 @@ static const struct palmas_clks_of_match_data palmas_of_clk32kgaudio = { | |||
148 | .init = { | 148 | .init = { |
149 | .name = "clk32kgaudio", | 149 | .name = "clk32kgaudio", |
150 | .ops = &palmas_clks_ops, | 150 | .ops = &palmas_clks_ops, |
151 | .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, | 151 | .flags = CLK_IGNORE_UNUSED, |
152 | }, | 152 | }, |
153 | .desc = { | 153 | .desc = { |
154 | .clk_name = "clk32kgaudio", | 154 | .clk_name = "clk32kgaudio", |
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 7bc1c4527ae4..58566a17944a 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c | |||
@@ -869,14 +869,15 @@ static void __init core_mux_init(struct device_node *np) | |||
869 | } | 869 | } |
870 | } | 870 | } |
871 | 871 | ||
872 | static struct clk *sysclk_from_fixed(struct device_node *node, const char *name) | 872 | static struct clk __init |
873 | *sysclk_from_fixed(struct device_node *node, const char *name) | ||
873 | { | 874 | { |
874 | u32 rate; | 875 | u32 rate; |
875 | 876 | ||
876 | if (of_property_read_u32(node, "clock-frequency", &rate)) | 877 | if (of_property_read_u32(node, "clock-frequency", &rate)) |
877 | return ERR_PTR(-ENODEV); | 878 | return ERR_PTR(-ENODEV); |
878 | 879 | ||
879 | return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); | 880 | return clk_register_fixed_rate(NULL, name, NULL, 0, rate); |
880 | } | 881 | } |
881 | 882 | ||
882 | static struct clk *sysclk_from_parent(const char *name) | 883 | static struct clk *sysclk_from_parent(const char *name) |
diff --git a/drivers/clk/clk-rk808.c b/drivers/clk/clk-rk808.c index 0fee2f4ca258..74383039761e 100644 --- a/drivers/clk/clk-rk808.c +++ b/drivers/clk/clk-rk808.c | |||
@@ -106,7 +106,6 @@ static int rk808_clkout_probe(struct platform_device *pdev) | |||
106 | if (!clk_table) | 106 | if (!clk_table) |
107 | return -ENOMEM; | 107 | return -ENOMEM; |
108 | 108 | ||
109 | init.flags = CLK_IS_ROOT; | ||
110 | init.parent_names = NULL; | 109 | init.parent_names = NULL; |
111 | init.num_parents = 0; | 110 | init.num_parents = 0; |
112 | init.name = "rk808-clkout1"; | 111 | init.name = "rk808-clkout1"; |
diff --git a/drivers/clk/clk-tango4.c b/drivers/clk/clk-tango4.c index 004ab7dfcfe3..eef75e305a59 100644 --- a/drivers/clk/clk-tango4.c +++ b/drivers/clk/clk-tango4.c | |||
@@ -4,17 +4,19 @@ | |||
4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | #include <linux/io.h> | 5 | #include <linux/io.h> |
6 | 6 | ||
7 | static struct clk *out[2]; | 7 | #define CLK_COUNT 4 /* cpu_clk, sys_clk, usb_clk, sdio_clk */ |
8 | static struct clk_onecell_data clk_data = { out, 2 }; | 8 | static struct clk *clks[CLK_COUNT]; |
9 | static struct clk_onecell_data clk_data = { clks, CLK_COUNT }; | ||
9 | 10 | ||
10 | #define SYSCLK_CTRL 0x20 | 11 | #define SYSCLK_DIV 0x20 |
11 | #define CPUCLK_CTRL 0x24 | 12 | #define CPUCLK_DIV 0x24 |
12 | #define LEGACY_DIV 0x3c | 13 | #define DIV_BYPASS BIT(23) |
13 | 14 | ||
14 | #define PLL_N(val) (((val) >> 0) & 0x7f) | 15 | /*** CLKGEN_PLL ***/ |
15 | #define PLL_K(val) (((val) >> 13) & 0x7) | 16 | #define extract_pll_n(val) ((val >> 0) & ((1u << 7) - 1)) |
16 | #define PLL_M(val) (((val) >> 16) & 0x7) | 17 | #define extract_pll_k(val) ((val >> 13) & ((1u << 3) - 1)) |
17 | #define DIV_INDEX(val) (((val) >> 8) & 0xf) | 18 | #define extract_pll_m(val) ((val >> 16) & ((1u << 3) - 1)) |
19 | #define extract_pll_isel(val) ((val >> 24) & ((1u << 3) - 1)) | ||
18 | 20 | ||
19 | static void __init make_pll(int idx, const char *parent, void __iomem *base) | 21 | static void __init make_pll(int idx, const char *parent, void __iomem *base) |
20 | { | 22 | { |
@@ -22,40 +24,61 @@ static void __init make_pll(int idx, const char *parent, void __iomem *base) | |||
22 | u32 val, mul, div; | 24 | u32 val, mul, div; |
23 | 25 | ||
24 | sprintf(name, "pll%d", idx); | 26 | sprintf(name, "pll%d", idx); |
25 | val = readl_relaxed(base + idx*8); | 27 | val = readl(base + idx * 8); |
26 | mul = PLL_N(val) + 1; | 28 | mul = extract_pll_n(val) + 1; |
27 | div = (PLL_M(val) + 1) << PLL_K(val); | 29 | div = (extract_pll_m(val) + 1) << extract_pll_k(val); |
28 | clk_register_fixed_factor(NULL, name, parent, 0, mul, div); | 30 | clk_register_fixed_factor(NULL, name, parent, 0, mul, div); |
31 | if (extract_pll_isel(val) != 1) | ||
32 | panic("%s: input not set to XTAL_IN\n", name); | ||
29 | } | 33 | } |
30 | 34 | ||
31 | static int __init get_div(void __iomem *base) | 35 | static void __init make_cd(int idx, void __iomem *base) |
32 | { | 36 | { |
33 | u8 sysclk_tab[16] = { 2, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 }; | 37 | char name[8]; |
34 | int idx = DIV_INDEX(readl_relaxed(base + LEGACY_DIV)); | 38 | u32 val, mul, div; |
35 | 39 | ||
36 | return sysclk_tab[idx]; | 40 | sprintf(name, "cd%d", idx); |
41 | val = readl(base + idx * 8); | ||
42 | mul = 1 << 27; | ||
43 | div = (2 << 27) + val; | ||
44 | clk_register_fixed_factor(NULL, name, "pll2", 0, mul, div); | ||
45 | if (val > 0xf0000000) | ||
46 | panic("%s: unsupported divider %x\n", name, val); | ||
37 | } | 47 | } |
38 | 48 | ||
39 | static void __init tango4_clkgen_setup(struct device_node *np) | 49 | static void __init tango4_clkgen_setup(struct device_node *np) |
40 | { | 50 | { |
41 | int div, ret; | 51 | struct clk **pp = clk_data.clks; |
42 | void __iomem *base = of_iomap(np, 0); | 52 | void __iomem *base = of_iomap(np, 0); |
43 | const char *parent = of_clk_get_parent_name(np, 0); | 53 | const char *parent = of_clk_get_parent_name(np, 0); |
44 | 54 | ||
45 | if (!base) | 55 | if (!base) |
46 | panic("%s: invalid address\n", np->full_name); | 56 | panic("%s: invalid address\n", np->name); |
57 | |||
58 | if (readl(base + CPUCLK_DIV) & DIV_BYPASS) | ||
59 | panic("%s: unsupported cpuclk setup\n", np->name); | ||
60 | |||
61 | if (readl(base + SYSCLK_DIV) & DIV_BYPASS) | ||
62 | panic("%s: unsupported sysclk setup\n", np->name); | ||
63 | |||
64 | writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */ | ||
47 | 65 | ||
48 | make_pll(0, parent, base); | 66 | make_pll(0, parent, base); |
49 | make_pll(1, parent, base); | 67 | make_pll(1, parent, base); |
68 | make_pll(2, parent, base); | ||
69 | make_cd(2, base + 0x80); | ||
70 | make_cd(6, base + 0x80); | ||
50 | 71 | ||
51 | out[0] = clk_register_divider(NULL, "cpuclk", "pll0", 0, | 72 | pp[0] = clk_register_divider(NULL, "cpu_clk", "pll0", 0, |
52 | base + CPUCLK_CTRL, 8, 8, CLK_DIVIDER_ONE_BASED, NULL); | 73 | base + CPUCLK_DIV, 8, 8, CLK_DIVIDER_ONE_BASED, NULL); |
74 | pp[1] = clk_register_fixed_factor(NULL, "sys_clk", "pll1", 0, 1, 4); | ||
75 | pp[2] = clk_register_fixed_factor(NULL, "usb_clk", "cd2", 0, 1, 2); | ||
76 | pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2); | ||
53 | 77 | ||
54 | div = readl_relaxed(base + SYSCLK_CTRL) & BIT(23) ? get_div(base) : 4; | 78 | if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3])) |
55 | out[1] = clk_register_fixed_factor(NULL, "sysclk", "pll1", 0, 1, div); | 79 | panic("%s: clk registration failed\n", np->name); |
56 | 80 | ||
57 | ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 81 | if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) |
58 | if (IS_ERR(out[0]) || IS_ERR(out[1]) || ret < 0) | 82 | panic("%s: clk provider registration failed\n", np->name); |
59 | panic("%s: clk registration failed\n", np->full_name); | ||
60 | } | 83 | } |
61 | CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup); | 84 | CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup); |
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c index 8e5ed649a098..697c66757400 100644 --- a/drivers/clk/clk-twl6040.c +++ b/drivers/clk/clk-twl6040.c | |||
@@ -74,7 +74,6 @@ static const struct clk_ops twl6040_mcpdm_ops = { | |||
74 | static struct clk_init_data wm831x_clkout_init = { | 74 | static struct clk_init_data wm831x_clkout_init = { |
75 | .name = "mcpdm_fclk", | 75 | .name = "mcpdm_fclk", |
76 | .ops = &twl6040_mcpdm_ops, | 76 | .ops = &twl6040_mcpdm_ops, |
77 | .flags = CLK_IS_ROOT, | ||
78 | }; | 77 | }; |
79 | 78 | ||
80 | static int twl6040_clk_probe(struct platform_device *pdev) | 79 | static int twl6040_clk_probe(struct platform_device *pdev) |
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index 43f9d15255f4..88def4b2761c 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c | |||
@@ -58,7 +58,6 @@ static const struct clk_ops wm831x_xtal_ops = { | |||
58 | static struct clk_init_data wm831x_xtal_init = { | 58 | static struct clk_init_data wm831x_xtal_init = { |
59 | .name = "xtal", | 59 | .name = "xtal", |
60 | .ops = &wm831x_xtal_ops, | 60 | .ops = &wm831x_xtal_ops, |
61 | .flags = CLK_IS_ROOT, | ||
62 | }; | 61 | }; |
63 | 62 | ||
64 | static const unsigned long wm831x_fll_auto_rates[] = { | 63 | static const unsigned long wm831x_fll_auto_rates[] = { |
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index d73450b60b28..343313250c58 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c | |||
@@ -198,7 +198,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty | |||
198 | of_property_read_string(np, "clock-output-names", &clk_name); | 198 | of_property_read_string(np, "clock-output-names", &clk_name); |
199 | clk = xgene_register_clk_pll(NULL, | 199 | clk = xgene_register_clk_pll(NULL, |
200 | clk_name, of_clk_get_parent_name(np, 0), | 200 | clk_name, of_clk_get_parent_name(np, 0), |
201 | CLK_IS_ROOT, reg, 0, pll_type, &clk_lock, | 201 | 0, reg, 0, pll_type, &clk_lock, |
202 | version); | 202 | version); |
203 | if (!IS_ERR(clk)) { | 203 | if (!IS_ERR(clk)) { |
204 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | 204 | of_clk_add_provider(np, of_clk_src_simple_get, clk); |
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..d584004f7af7 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -574,6 +574,9 @@ static void clk_core_unprepare(struct clk_core *core) | |||
574 | if (WARN_ON(core->prepare_count == 0)) | 574 | if (WARN_ON(core->prepare_count == 0)) |
575 | return; | 575 | return; |
576 | 576 | ||
577 | if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL)) | ||
578 | return; | ||
579 | |||
577 | if (--core->prepare_count > 0) | 580 | if (--core->prepare_count > 0) |
578 | return; | 581 | return; |
579 | 582 | ||
@@ -679,6 +682,9 @@ static void clk_core_disable(struct clk_core *core) | |||
679 | if (WARN_ON(core->enable_count == 0)) | 682 | if (WARN_ON(core->enable_count == 0)) |
680 | return; | 683 | return; |
681 | 684 | ||
685 | if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL)) | ||
686 | return; | ||
687 | |||
682 | if (--core->enable_count > 0) | 688 | if (--core->enable_count > 0) |
683 | return; | 689 | return; |
684 | 690 | ||
@@ -2397,6 +2403,16 @@ static int __clk_core_init(struct clk_core *core) | |||
2397 | if (core->ops->init) | 2403 | if (core->ops->init) |
2398 | core->ops->init(core->hw); | 2404 | core->ops->init(core->hw); |
2399 | 2405 | ||
2406 | if (core->flags & CLK_IS_CRITICAL) { | ||
2407 | unsigned long flags; | ||
2408 | |||
2409 | clk_core_prepare(core); | ||
2410 | |||
2411 | flags = clk_enable_lock(); | ||
2412 | clk_core_enable(core); | ||
2413 | clk_enable_unlock(flags); | ||
2414 | } | ||
2415 | |||
2400 | kref_init(&core->ref); | 2416 | kref_init(&core->ref); |
2401 | out: | 2417 | out: |
2402 | clk_prepare_unlock(); | 2418 | clk_prepare_unlock(); |
@@ -2536,6 +2552,22 @@ fail_out: | |||
2536 | } | 2552 | } |
2537 | EXPORT_SYMBOL_GPL(clk_register); | 2553 | EXPORT_SYMBOL_GPL(clk_register); |
2538 | 2554 | ||
2555 | /** | ||
2556 | * clk_hw_register - register a clk_hw and return an error code | ||
2557 | * @dev: device that is registering this clock | ||
2558 | * @hw: link to hardware-specific clock data | ||
2559 | * | ||
2560 | * clk_hw_register is the primary interface for populating the clock tree with | ||
2561 | * new clock nodes. It returns an integer equal to zero indicating success or | ||
2562 | * less than zero indicating failure. Drivers must test for an error code after | ||
2563 | * calling clk_hw_register(). | ||
2564 | */ | ||
2565 | int clk_hw_register(struct device *dev, struct clk_hw *hw) | ||
2566 | { | ||
2567 | return PTR_ERR_OR_ZERO(clk_register(dev, hw)); | ||
2568 | } | ||
2569 | EXPORT_SYMBOL_GPL(clk_hw_register); | ||
2570 | |||
2539 | /* Free memory allocated for a clock. */ | 2571 | /* Free memory allocated for a clock. */ |
2540 | static void __clk_release(struct kref *ref) | 2572 | static void __clk_release(struct kref *ref) |
2541 | { | 2573 | { |
@@ -2637,11 +2669,26 @@ unlock: | |||
2637 | } | 2669 | } |
2638 | EXPORT_SYMBOL_GPL(clk_unregister); | 2670 | EXPORT_SYMBOL_GPL(clk_unregister); |
2639 | 2671 | ||
2672 | /** | ||
2673 | * clk_hw_unregister - unregister a currently registered clk_hw | ||
2674 | * @hw: hardware-specific clock data to unregister | ||
2675 | */ | ||
2676 | void clk_hw_unregister(struct clk_hw *hw) | ||
2677 | { | ||
2678 | clk_unregister(hw->clk); | ||
2679 | } | ||
2680 | EXPORT_SYMBOL_GPL(clk_hw_unregister); | ||
2681 | |||
2640 | static void devm_clk_release(struct device *dev, void *res) | 2682 | static void devm_clk_release(struct device *dev, void *res) |
2641 | { | 2683 | { |
2642 | clk_unregister(*(struct clk **)res); | 2684 | clk_unregister(*(struct clk **)res); |
2643 | } | 2685 | } |
2644 | 2686 | ||
2687 | static void devm_clk_hw_release(struct device *dev, void *res) | ||
2688 | { | ||
2689 | clk_hw_unregister(*(struct clk_hw **)res); | ||
2690 | } | ||
2691 | |||
2645 | /** | 2692 | /** |
2646 | * devm_clk_register - resource managed clk_register() | 2693 | * devm_clk_register - resource managed clk_register() |
2647 | * @dev: device that is registering this clock | 2694 | * @dev: device that is registering this clock |
@@ -2672,6 +2719,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) | |||
2672 | } | 2719 | } |
2673 | EXPORT_SYMBOL_GPL(devm_clk_register); | 2720 | EXPORT_SYMBOL_GPL(devm_clk_register); |
2674 | 2721 | ||
2722 | /** | ||
2723 | * devm_clk_hw_register - resource managed clk_hw_register() | ||
2724 | * @dev: device that is registering this clock | ||
2725 | * @hw: link to hardware-specific clock data | ||
2726 | * | ||
2727 | * Managed clk_hw_register(). Clocks registered by this function are | ||
2728 | * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register() | ||
2729 | * for more information. | ||
2730 | */ | ||
2731 | int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) | ||
2732 | { | ||
2733 | struct clk_hw **hwp; | ||
2734 | int ret; | ||
2735 | |||
2736 | hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); | ||
2737 | if (!hwp) | ||
2738 | return -ENOMEM; | ||
2739 | |||
2740 | ret = clk_hw_register(dev, hw); | ||
2741 | if (!ret) { | ||
2742 | *hwp = hw; | ||
2743 | devres_add(dev, hwp); | ||
2744 | } else { | ||
2745 | devres_free(hwp); | ||
2746 | } | ||
2747 | |||
2748 | return ret; | ||
2749 | } | ||
2750 | EXPORT_SYMBOL_GPL(devm_clk_hw_register); | ||
2751 | |||
2675 | static int devm_clk_match(struct device *dev, void *res, void *data) | 2752 | static int devm_clk_match(struct device *dev, void *res, void *data) |
2676 | { | 2753 | { |
2677 | struct clk *c = res; | 2754 | struct clk *c = res; |
@@ -2680,6 +2757,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data) | |||
2680 | return c == data; | 2757 | return c == data; |
2681 | } | 2758 | } |
2682 | 2759 | ||
2760 | static int devm_clk_hw_match(struct device *dev, void *res, void *data) | ||
2761 | { | ||
2762 | struct clk_hw *hw = res; | ||
2763 | |||
2764 | if (WARN_ON(!hw)) | ||
2765 | return 0; | ||
2766 | return hw == data; | ||
2767 | } | ||
2768 | |||
2683 | /** | 2769 | /** |
2684 | * devm_clk_unregister - resource managed clk_unregister() | 2770 | * devm_clk_unregister - resource managed clk_unregister() |
2685 | * @clk: clock to unregister | 2771 | * @clk: clock to unregister |
@@ -2694,6 +2780,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) | |||
2694 | } | 2780 | } |
2695 | EXPORT_SYMBOL_GPL(devm_clk_unregister); | 2781 | EXPORT_SYMBOL_GPL(devm_clk_unregister); |
2696 | 2782 | ||
2783 | /** | ||
2784 | * devm_clk_hw_unregister - resource managed clk_hw_unregister() | ||
2785 | * @dev: device that is unregistering the hardware-specific clock data | ||
2786 | * @hw: link to hardware-specific clock data | ||
2787 | * | ||
2788 | * Unregister a clk_hw registered with devm_clk_hw_register(). Normally | ||
2789 | * this function will not need to be called and the resource management | ||
2790 | * code will ensure that the resource is freed. | ||
2791 | */ | ||
2792 | void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) | ||
2793 | { | ||
2794 | WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, | ||
2795 | hw)); | ||
2796 | } | ||
2797 | EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); | ||
2798 | |||
2697 | /* | 2799 | /* |
2698 | * clkdev helpers | 2800 | * clkdev helpers |
2699 | */ | 2801 | */ |
@@ -2855,6 +2957,7 @@ struct of_clk_provider { | |||
2855 | 2957 | ||
2856 | struct device_node *node; | 2958 | struct device_node *node; |
2857 | struct clk *(*get)(struct of_phandle_args *clkspec, void *data); | 2959 | struct clk *(*get)(struct of_phandle_args *clkspec, void *data); |
2960 | struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data); | ||
2858 | void *data; | 2961 | void *data; |
2859 | }; | 2962 | }; |
2860 | 2963 | ||
@@ -2871,6 +2974,12 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, | |||
2871 | } | 2974 | } |
2872 | EXPORT_SYMBOL_GPL(of_clk_src_simple_get); | 2975 | EXPORT_SYMBOL_GPL(of_clk_src_simple_get); |
2873 | 2976 | ||
2977 | struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data) | ||
2978 | { | ||
2979 | return data; | ||
2980 | } | ||
2981 | EXPORT_SYMBOL_GPL(of_clk_hw_simple_get); | ||
2982 | |||
2874 | struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) | 2983 | struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) |
2875 | { | 2984 | { |
2876 | struct clk_onecell_data *clk_data = data; | 2985 | struct clk_onecell_data *clk_data = data; |
@@ -2885,6 +2994,21 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) | |||
2885 | } | 2994 | } |
2886 | EXPORT_SYMBOL_GPL(of_clk_src_onecell_get); | 2995 | EXPORT_SYMBOL_GPL(of_clk_src_onecell_get); |
2887 | 2996 | ||
2997 | struct clk_hw * | ||
2998 | of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data) | ||
2999 | { | ||
3000 | struct clk_hw_onecell_data *hw_data = data; | ||
3001 | unsigned int idx = clkspec->args[0]; | ||
3002 | |||
3003 | if (idx >= hw_data->num) { | ||
3004 | pr_err("%s: invalid index %u\n", __func__, idx); | ||
3005 | return ERR_PTR(-EINVAL); | ||
3006 | } | ||
3007 | |||
3008 | return hw_data->hws[idx]; | ||
3009 | } | ||
3010 | EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get); | ||
3011 | |||
2888 | /** | 3012 | /** |
2889 | * of_clk_add_provider() - Register a clock provider for a node | 3013 | * of_clk_add_provider() - Register a clock provider for a node |
2890 | * @np: Device node pointer associated with clock provider | 3014 | * @np: Device node pointer associated with clock provider |
@@ -2921,6 +3045,41 @@ int of_clk_add_provider(struct device_node *np, | |||
2921 | EXPORT_SYMBOL_GPL(of_clk_add_provider); | 3045 | EXPORT_SYMBOL_GPL(of_clk_add_provider); |
2922 | 3046 | ||
2923 | /** | 3047 | /** |
3048 | * of_clk_add_hw_provider() - Register a clock provider for a node | ||
3049 | * @np: Device node pointer associated with clock provider | ||
3050 | * @get: callback for decoding clk_hw | ||
3051 | * @data: context pointer for @get callback. | ||
3052 | */ | ||
3053 | int of_clk_add_hw_provider(struct device_node *np, | ||
3054 | struct clk_hw *(*get)(struct of_phandle_args *clkspec, | ||
3055 | void *data), | ||
3056 | void *data) | ||
3057 | { | ||
3058 | struct of_clk_provider *cp; | ||
3059 | int ret; | ||
3060 | |||
3061 | cp = kzalloc(sizeof(*cp), GFP_KERNEL); | ||
3062 | if (!cp) | ||
3063 | return -ENOMEM; | ||
3064 | |||
3065 | cp->node = of_node_get(np); | ||
3066 | cp->data = data; | ||
3067 | cp->get_hw = get; | ||
3068 | |||
3069 | mutex_lock(&of_clk_mutex); | ||
3070 | list_add(&cp->link, &of_clk_providers); | ||
3071 | mutex_unlock(&of_clk_mutex); | ||
3072 | pr_debug("Added clk_hw provider from %s\n", np->full_name); | ||
3073 | |||
3074 | ret = of_clk_set_defaults(np, true); | ||
3075 | if (ret < 0) | ||
3076 | of_clk_del_provider(np); | ||
3077 | |||
3078 | return ret; | ||
3079 | } | ||
3080 | EXPORT_SYMBOL_GPL(of_clk_add_hw_provider); | ||
3081 | |||
3082 | /** | ||
2924 | * of_clk_del_provider() - Remove a previously registered clock provider | 3083 | * of_clk_del_provider() - Remove a previously registered clock provider |
2925 | * @np: Device node pointer associated with clock provider | 3084 | * @np: Device node pointer associated with clock provider |
2926 | */ | 3085 | */ |
@@ -2941,11 +3100,32 @@ void of_clk_del_provider(struct device_node *np) | |||
2941 | } | 3100 | } |
2942 | EXPORT_SYMBOL_GPL(of_clk_del_provider); | 3101 | EXPORT_SYMBOL_GPL(of_clk_del_provider); |
2943 | 3102 | ||
3103 | static struct clk_hw * | ||
3104 | __of_clk_get_hw_from_provider(struct of_clk_provider *provider, | ||
3105 | struct of_phandle_args *clkspec) | ||
3106 | { | ||
3107 | struct clk *clk; | ||
3108 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); | ||
3109 | |||
3110 | if (provider->get_hw) { | ||
3111 | hw = provider->get_hw(clkspec, provider->data); | ||
3112 | } else if (provider->get) { | ||
3113 | clk = provider->get(clkspec, provider->data); | ||
3114 | if (!IS_ERR(clk)) | ||
3115 | hw = __clk_get_hw(clk); | ||
3116 | else | ||
3117 | hw = ERR_CAST(clk); | ||
3118 | } | ||
3119 | |||
3120 | return hw; | ||
3121 | } | ||
3122 | |||
2944 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | 3123 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, |
2945 | const char *dev_id, const char *con_id) | 3124 | const char *dev_id, const char *con_id) |
2946 | { | 3125 | { |
2947 | struct of_clk_provider *provider; | 3126 | struct of_clk_provider *provider; |
2948 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); | 3127 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); |
3128 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); | ||
2949 | 3129 | ||
2950 | if (!clkspec) | 3130 | if (!clkspec) |
2951 | return ERR_PTR(-EINVAL); | 3131 | return ERR_PTR(-EINVAL); |
@@ -2954,10 +3134,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
2954 | mutex_lock(&of_clk_mutex); | 3134 | mutex_lock(&of_clk_mutex); |
2955 | list_for_each_entry(provider, &of_clk_providers, link) { | 3135 | list_for_each_entry(provider, &of_clk_providers, link) { |
2956 | if (provider->node == clkspec->np) | 3136 | if (provider->node == clkspec->np) |
2957 | clk = provider->get(clkspec, provider->data); | 3137 | hw = __of_clk_get_hw_from_provider(provider, clkspec); |
2958 | if (!IS_ERR(clk)) { | 3138 | if (!IS_ERR(hw)) { |
2959 | clk = __clk_create_clk(__clk_get_hw(clk), dev_id, | 3139 | clk = __clk_create_clk(hw, dev_id, con_id); |
2960 | con_id); | ||
2961 | 3140 | ||
2962 | if (!IS_ERR(clk) && !__clk_get(clk)) { | 3141 | if (!IS_ERR(clk) && !__clk_get(clk)) { |
2963 | __clk_free_clk(clk); | 3142 | __clk_free_clk(clk); |
@@ -3127,6 +3306,41 @@ static int parent_ready(struct device_node *np) | |||
3127 | } | 3306 | } |
3128 | 3307 | ||
3129 | /** | 3308 | /** |
3309 | * of_clk_detect_critical() - set CLK_IS_CRITICAL flag from Device Tree | ||
3310 | * @np: Device node pointer associated with clock provider | ||
3311 | * @index: clock index | ||
3312 | * @flags: pointer to clk_core->flags | ||
3313 | * | ||
3314 | * Detects if the clock-critical property exists and, if so, sets the | ||
3315 | * corresponding CLK_IS_CRITICAL flag. | ||
3316 | * | ||
3317 | * Do not use this function. It exists only for legacy Device Tree | ||
3318 | * bindings, such as the one-clock-per-node style that are outdated. | ||
3319 | * Those bindings typically put all clock data into .dts and the Linux | ||
3320 | * driver has no clock data, thus making it impossible to set this flag | ||
3321 | * correctly from the driver. Only those drivers may call | ||
3322 | * of_clk_detect_critical from their setup functions. | ||
3323 | * | ||
3324 | * Return: error code or zero on success | ||
3325 | */ | ||
3326 | int of_clk_detect_critical(struct device_node *np, | ||
3327 | int index, unsigned long *flags) | ||
3328 | { | ||
3329 | struct property *prop; | ||
3330 | const __be32 *cur; | ||
3331 | uint32_t idx; | ||
3332 | |||
3333 | if (!np || !flags) | ||
3334 | return -EINVAL; | ||
3335 | |||
3336 | of_property_for_each_u32(np, "clock-critical", prop, cur, idx) | ||
3337 | if (index == idx) | ||
3338 | *flags |= CLK_IS_CRITICAL; | ||
3339 | |||
3340 | return 0; | ||
3341 | } | ||
3342 | |||
3343 | /** | ||
3130 | * of_clk_init() - Scan and init clock providers from the DT | 3344 | * of_clk_init() - Scan and init clock providers from the DT |
3131 | * @matches: array of compatible values and init functions for providers. | 3345 | * @matches: array of compatible values and init functions for providers. |
3132 | * | 3346 | * |
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index eb20b941154b..89cc700fbc37 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
@@ -301,6 +301,20 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) | |||
301 | } | 301 | } |
302 | EXPORT_SYMBOL(clkdev_alloc); | 302 | EXPORT_SYMBOL(clkdev_alloc); |
303 | 303 | ||
304 | struct clk_lookup * | ||
305 | clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...) | ||
306 | { | ||
307 | struct clk_lookup *cl; | ||
308 | va_list ap; | ||
309 | |||
310 | va_start(ap, dev_fmt); | ||
311 | cl = vclkdev_alloc(hw, con_id, dev_fmt, ap); | ||
312 | va_end(ap); | ||
313 | |||
314 | return cl; | ||
315 | } | ||
316 | EXPORT_SYMBOL(clkdev_hw_alloc); | ||
317 | |||
304 | /** | 318 | /** |
305 | * clkdev_create - allocate and add a clkdev lookup structure | 319 | * clkdev_create - allocate and add a clkdev lookup structure |
306 | * @clk: struct clk to associate with all clk_lookups | 320 | * @clk: struct clk to associate with all clk_lookups |
@@ -324,6 +338,29 @@ struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, | |||
324 | } | 338 | } |
325 | EXPORT_SYMBOL_GPL(clkdev_create); | 339 | EXPORT_SYMBOL_GPL(clkdev_create); |
326 | 340 | ||
341 | /** | ||
342 | * clkdev_hw_create - allocate and add a clkdev lookup structure | ||
343 | * @hw: struct clk_hw to associate with all clk_lookups | ||
344 | * @con_id: connection ID string on device | ||
345 | * @dev_fmt: format string describing device name | ||
346 | * | ||
347 | * Returns a clk_lookup structure, which can be later unregistered and | ||
348 | * freed. | ||
349 | */ | ||
350 | struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id, | ||
351 | const char *dev_fmt, ...) | ||
352 | { | ||
353 | struct clk_lookup *cl; | ||
354 | va_list ap; | ||
355 | |||
356 | va_start(ap, dev_fmt); | ||
357 | cl = vclkdev_create(hw, con_id, dev_fmt, ap); | ||
358 | va_end(ap); | ||
359 | |||
360 | return cl; | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(clkdev_hw_create); | ||
363 | |||
327 | int clk_add_alias(const char *alias, const char *alias_dev_name, | 364 | int clk_add_alias(const char *alias, const char *alias_dev_name, |
328 | const char *con_id, struct device *dev) | 365 | const char *con_id, struct device *dev) |
329 | { | 366 | { |
@@ -404,28 +441,28 @@ int clk_register_clkdev(struct clk *clk, const char *con_id, | |||
404 | EXPORT_SYMBOL(clk_register_clkdev); | 441 | EXPORT_SYMBOL(clk_register_clkdev); |
405 | 442 | ||
406 | /** | 443 | /** |
407 | * clk_register_clkdevs - register a set of clk_lookup for a struct clk | 444 | * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw |
408 | * @clk: struct clk to associate with all clk_lookups | 445 | * @hw: struct clk_hw to associate with all clk_lookups |
409 | * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized | 446 | * @con_id: connection ID string on device |
410 | * @num: number of clk_lookup structures to register | 447 | * @dev_id: format string describing device name |
411 | * | 448 | * |
412 | * To make things easier for mass registration, we detect error clks | 449 | * con_id or dev_id may be NULL as a wildcard, just as in the rest of |
413 | * from a previous clk_register() call, and return the error code for | 450 | * clkdev. |
414 | * those. This is to permit this function to be called immediately | ||
415 | * after clk_register(). | ||
416 | */ | 451 | */ |
417 | int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num) | 452 | int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id, |
453 | const char *dev_id) | ||
418 | { | 454 | { |
419 | unsigned i; | 455 | struct clk_lookup *cl; |
420 | |||
421 | if (IS_ERR(clk)) | ||
422 | return PTR_ERR(clk); | ||
423 | 456 | ||
424 | for (i = 0; i < num; i++, cl++) { | 457 | /* |
425 | cl->clk_hw = __clk_get_hw(clk); | 458 | * Since dev_id can be NULL, and NULL is handled specially, we must |
426 | __clkdev_add(cl); | 459 | * pass it as either a NULL format string, or with "%s". |
427 | } | 460 | */ |
461 | if (dev_id) | ||
462 | cl = __clk_register_clkdev(hw, con_id, "%s", dev_id); | ||
463 | else | ||
464 | cl = __clk_register_clkdev(hw, con_id, NULL); | ||
428 | 465 | ||
429 | return 0; | 466 | return cl ? 0 : -ENOMEM; |
430 | } | 467 | } |
431 | EXPORT_SYMBOL(clk_register_clkdevs); | 468 | EXPORT_SYMBOL(clk_hw_register_clkdev); |
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig index e43485448612..3f537a04c6a6 100644 --- a/drivers/clk/hisilicon/Kconfig +++ b/drivers/clk/hisilicon/Kconfig | |||
@@ -1,3 +1,11 @@ | |||
1 | config COMMON_CLK_HI3519 | ||
2 | tristate "Hi3519 Clock Driver" | ||
3 | depends on ARCH_HISI || COMPILE_TEST | ||
4 | select RESET_HISI | ||
5 | default ARCH_HISI | ||
6 | help | ||
7 | Build the clock driver for hi3519. | ||
8 | |||
1 | config COMMON_CLK_HI6220 | 9 | config COMMON_CLK_HI6220 |
2 | bool "Hi6220 Clock Driver" | 10 | bool "Hi6220 Clock Driver" |
3 | depends on ARCH_HISI || COMPILE_TEST | 11 | depends on ARCH_HISI || COMPILE_TEST |
@@ -5,6 +13,13 @@ config COMMON_CLK_HI6220 | |||
5 | help | 13 | help |
6 | Build the Hisilicon Hi6220 clock driver based on the common clock framework. | 14 | Build the Hisilicon Hi6220 clock driver based on the common clock framework. |
7 | 15 | ||
16 | config RESET_HISI | ||
17 | bool "HiSilicon Reset Controller Driver" | ||
18 | depends on ARCH_HISI || COMPILE_TEST | ||
19 | select RESET_CONTROLLER | ||
20 | help | ||
21 | Build reset controller driver for HiSilicon device chipsets. | ||
22 | |||
8 | config STUB_CLK_HI6220 | 23 | config STUB_CLK_HI6220 |
9 | bool "Hi6220 Stub Clock Driver" | 24 | bool "Hi6220 Stub Clock Driver" |
10 | depends on COMMON_CLK_HI6220 && MAILBOX | 25 | depends on COMMON_CLK_HI6220 && MAILBOX |
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile index 74dba31590f9..e169ec7da023 100644 --- a/drivers/clk/hisilicon/Makefile +++ b/drivers/clk/hisilicon/Makefile | |||
@@ -7,5 +7,7 @@ obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o | |||
7 | obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o | 7 | obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o |
8 | obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o | 8 | obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o |
9 | obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o | 9 | obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o |
10 | obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o | ||
10 | obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o | 11 | obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o |
12 | obj-$(CONFIG_RESET_HISI) += reset.o | ||
11 | obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o | 13 | obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o |
diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c new file mode 100644 index 000000000000..715c7301a66a --- /dev/null +++ b/drivers/clk/hisilicon/clk-hi3519.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Hi3519 Clock Driver | ||
3 | * | ||
4 | * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <dt-bindings/clock/hi3519-clock.h> | ||
21 | #include <linux/clk-provider.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include "clk.h" | ||
25 | #include "reset.h" | ||
26 | |||
27 | #define HI3519_INNER_CLK_OFFSET 64 | ||
28 | #define HI3519_FIXED_24M 65 | ||
29 | #define HI3519_FIXED_50M 66 | ||
30 | #define HI3519_FIXED_75M 67 | ||
31 | #define HI3519_FIXED_125M 68 | ||
32 | #define HI3519_FIXED_150M 69 | ||
33 | #define HI3519_FIXED_200M 70 | ||
34 | #define HI3519_FIXED_250M 71 | ||
35 | #define HI3519_FIXED_300M 72 | ||
36 | #define HI3519_FIXED_400M 73 | ||
37 | #define HI3519_FMC_MUX 74 | ||
38 | |||
39 | #define HI3519_NR_CLKS 128 | ||
40 | |||
41 | static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = { | ||
42 | { HI3519_FIXED_24M, "24m", NULL, 0, 24000000, }, | ||
43 | { HI3519_FIXED_50M, "50m", NULL, 0, 50000000, }, | ||
44 | { HI3519_FIXED_75M, "75m", NULL, 0, 75000000, }, | ||
45 | { HI3519_FIXED_125M, "125m", NULL, 0, 125000000, }, | ||
46 | { HI3519_FIXED_150M, "150m", NULL, 0, 150000000, }, | ||
47 | { HI3519_FIXED_200M, "200m", NULL, 0, 200000000, }, | ||
48 | { HI3519_FIXED_250M, "250m", NULL, 0, 250000000, }, | ||
49 | { HI3519_FIXED_300M, "300m", NULL, 0, 300000000, }, | ||
50 | { HI3519_FIXED_400M, "400m", NULL, 0, 400000000, }, | ||
51 | }; | ||
52 | |||
53 | static const char *const fmc_mux_p[] = { | ||
54 | "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m", }; | ||
55 | static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
56 | |||
57 | static const struct hisi_mux_clock hi3519_mux_clks[] = { | ||
58 | { HI3519_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), | ||
59 | CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, | ||
60 | }; | ||
61 | |||
62 | static const struct hisi_gate_clock hi3519_gate_clks[] = { | ||
63 | { HI3519_FMC_CLK, "clk_fmc", "fmc_mux", | ||
64 | CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, | ||
65 | { HI3519_UART0_CLK, "clk_uart0", "24m", | ||
66 | CLK_SET_RATE_PARENT, 0xe4, 20, 0, }, | ||
67 | { HI3519_UART1_CLK, "clk_uart1", "24m", | ||
68 | CLK_SET_RATE_PARENT, 0xe4, 21, 0, }, | ||
69 | { HI3519_UART2_CLK, "clk_uart2", "24m", | ||
70 | CLK_SET_RATE_PARENT, 0xe4, 22, 0, }, | ||
71 | { HI3519_UART3_CLK, "clk_uart3", "24m", | ||
72 | CLK_SET_RATE_PARENT, 0xe4, 23, 0, }, | ||
73 | { HI3519_UART4_CLK, "clk_uart4", "24m", | ||
74 | CLK_SET_RATE_PARENT, 0xe4, 24, 0, }, | ||
75 | { HI3519_SPI0_CLK, "clk_spi0", "50m", | ||
76 | CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, | ||
77 | { HI3519_SPI1_CLK, "clk_spi1", "50m", | ||
78 | CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, | ||
79 | { HI3519_SPI2_CLK, "clk_spi2", "50m", | ||
80 | CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, | ||
81 | }; | ||
82 | |||
83 | static int hi3519_clk_probe(struct platform_device *pdev) | ||
84 | { | ||
85 | struct device_node *np = pdev->dev.of_node; | ||
86 | struct hisi_clock_data *clk_data; | ||
87 | struct hisi_reset_controller *rstc; | ||
88 | |||
89 | rstc = hisi_reset_init(np); | ||
90 | if (!rstc) | ||
91 | return -ENOMEM; | ||
92 | |||
93 | clk_data = hisi_clk_init(np, HI3519_NR_CLKS); | ||
94 | if (!clk_data) { | ||
95 | hisi_reset_exit(rstc); | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks, | ||
100 | ARRAY_SIZE(hi3519_fixed_rate_clks), | ||
101 | clk_data); | ||
102 | hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks), | ||
103 | clk_data); | ||
104 | hisi_clk_register_gate(hi3519_gate_clks, | ||
105 | ARRAY_SIZE(hi3519_gate_clks), clk_data); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static const struct of_device_id hi3519_clk_match_table[] = { | ||
111 | { .compatible = "hisilicon,hi3519-crg" }, | ||
112 | { } | ||
113 | }; | ||
114 | MODULE_DEVICE_TABLE(of, hi3519_clk_match_table); | ||
115 | |||
116 | static struct platform_driver hi3519_clk_driver = { | ||
117 | .probe = hi3519_clk_probe, | ||
118 | .driver = { | ||
119 | .name = "hi3519-clk", | ||
120 | .of_match_table = hi3519_clk_match_table, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static int __init hi3519_clk_init(void) | ||
125 | { | ||
126 | return platform_driver_register(&hi3519_clk_driver); | ||
127 | } | ||
128 | core_initcall(hi3519_clk_init); | ||
129 | |||
130 | MODULE_LICENSE("GPL v2"); | ||
131 | MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver"); | ||
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 9f8e76676553..9b15adbfc30c 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c | |||
@@ -37,7 +37,7 @@ | |||
37 | 37 | ||
38 | static DEFINE_SPINLOCK(hisi_clk_lock); | 38 | static DEFINE_SPINLOCK(hisi_clk_lock); |
39 | 39 | ||
40 | struct hisi_clock_data __init *hisi_clk_init(struct device_node *np, | 40 | struct hisi_clock_data *hisi_clk_init(struct device_node *np, |
41 | int nr_clks) | 41 | int nr_clks) |
42 | { | 42 | { |
43 | struct hisi_clock_data *clk_data; | 43 | struct hisi_clock_data *clk_data; |
@@ -71,8 +71,9 @@ err_data: | |||
71 | err: | 71 | err: |
72 | return NULL; | 72 | return NULL; |
73 | } | 73 | } |
74 | EXPORT_SYMBOL_GPL(hisi_clk_init); | ||
74 | 75 | ||
75 | void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, | 76 | void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks, |
76 | int nums, struct hisi_clock_data *data) | 77 | int nums, struct hisi_clock_data *data) |
77 | { | 78 | { |
78 | struct clk *clk; | 79 | struct clk *clk; |
@@ -91,8 +92,9 @@ void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, | |||
91 | data->clk_data.clks[clks[i].id] = clk; | 92 | data->clk_data.clks[clks[i].id] = clk; |
92 | } | 93 | } |
93 | } | 94 | } |
95 | EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate); | ||
94 | 96 | ||
95 | void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, | 97 | void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks, |
96 | int nums, | 98 | int nums, |
97 | struct hisi_clock_data *data) | 99 | struct hisi_clock_data *data) |
98 | { | 100 | { |
@@ -112,8 +114,9 @@ void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, | |||
112 | data->clk_data.clks[clks[i].id] = clk; | 114 | data->clk_data.clks[clks[i].id] = clk; |
113 | } | 115 | } |
114 | } | 116 | } |
117 | EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor); | ||
115 | 118 | ||
116 | void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, | 119 | void hisi_clk_register_mux(const struct hisi_mux_clock *clks, |
117 | int nums, struct hisi_clock_data *data) | 120 | int nums, struct hisi_clock_data *data) |
118 | { | 121 | { |
119 | struct clk *clk; | 122 | struct clk *clk; |
@@ -141,8 +144,9 @@ void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, | |||
141 | data->clk_data.clks[clks[i].id] = clk; | 144 | data->clk_data.clks[clks[i].id] = clk; |
142 | } | 145 | } |
143 | } | 146 | } |
147 | EXPORT_SYMBOL_GPL(hisi_clk_register_mux); | ||
144 | 148 | ||
145 | void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, | 149 | void hisi_clk_register_divider(const struct hisi_divider_clock *clks, |
146 | int nums, struct hisi_clock_data *data) | 150 | int nums, struct hisi_clock_data *data) |
147 | { | 151 | { |
148 | struct clk *clk; | 152 | struct clk *clk; |
@@ -170,8 +174,9 @@ void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, | |||
170 | data->clk_data.clks[clks[i].id] = clk; | 174 | data->clk_data.clks[clks[i].id] = clk; |
171 | } | 175 | } |
172 | } | 176 | } |
177 | EXPORT_SYMBOL_GPL(hisi_clk_register_divider); | ||
173 | 178 | ||
174 | void __init hisi_clk_register_gate(struct hisi_gate_clock *clks, | 179 | void hisi_clk_register_gate(const struct hisi_gate_clock *clks, |
175 | int nums, struct hisi_clock_data *data) | 180 | int nums, struct hisi_clock_data *data) |
176 | { | 181 | { |
177 | struct clk *clk; | 182 | struct clk *clk; |
@@ -198,8 +203,9 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *clks, | |||
198 | data->clk_data.clks[clks[i].id] = clk; | 203 | data->clk_data.clks[clks[i].id] = clk; |
199 | } | 204 | } |
200 | } | 205 | } |
206 | EXPORT_SYMBOL_GPL(hisi_clk_register_gate); | ||
201 | 207 | ||
202 | void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, | 208 | void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks, |
203 | int nums, struct hisi_clock_data *data) | 209 | int nums, struct hisi_clock_data *data) |
204 | { | 210 | { |
205 | struct clk *clk; | 211 | struct clk *clk; |
@@ -226,8 +232,9 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, | |||
226 | data->clk_data.clks[clks[i].id] = clk; | 232 | data->clk_data.clks[clks[i].id] = clk; |
227 | } | 233 | } |
228 | } | 234 | } |
235 | EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep); | ||
229 | 236 | ||
230 | void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks, | 237 | void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks, |
231 | int nums, struct hisi_clock_data *data) | 238 | int nums, struct hisi_clock_data *data) |
232 | { | 239 | { |
233 | struct clk *clk; | 240 | struct clk *clk; |
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index b56fbc1c5f27..20d64afe4ad8 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h | |||
@@ -111,18 +111,18 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, | |||
111 | u8 shift, u8 width, u32 mask_bit, spinlock_t *lock); | 111 | u8 shift, u8 width, u32 mask_bit, spinlock_t *lock); |
112 | 112 | ||
113 | struct hisi_clock_data *hisi_clk_init(struct device_node *, int); | 113 | struct hisi_clock_data *hisi_clk_init(struct device_node *, int); |
114 | void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *, | 114 | void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *, |
115 | int, struct hisi_clock_data *); | 115 | int, struct hisi_clock_data *); |
116 | void hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *, | 116 | void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *, |
117 | int, struct hisi_clock_data *); | 117 | int, struct hisi_clock_data *); |
118 | void hisi_clk_register_mux(struct hisi_mux_clock *, int, | 118 | void hisi_clk_register_mux(const struct hisi_mux_clock *, int, |
119 | struct hisi_clock_data *); | 119 | struct hisi_clock_data *); |
120 | void hisi_clk_register_divider(struct hisi_divider_clock *, | 120 | void hisi_clk_register_divider(const struct hisi_divider_clock *, |
121 | int, struct hisi_clock_data *); | 121 | int, struct hisi_clock_data *); |
122 | void hisi_clk_register_gate(struct hisi_gate_clock *, | 122 | void hisi_clk_register_gate(const struct hisi_gate_clock *, |
123 | int, struct hisi_clock_data *); | 123 | int, struct hisi_clock_data *); |
124 | void hisi_clk_register_gate_sep(struct hisi_gate_clock *, | 124 | void hisi_clk_register_gate_sep(const struct hisi_gate_clock *, |
125 | int, struct hisi_clock_data *); | 125 | int, struct hisi_clock_data *); |
126 | void hi6220_clk_register_divider(struct hi6220_divider_clock *, | 126 | void hi6220_clk_register_divider(const struct hi6220_divider_clock *, |
127 | int, struct hisi_clock_data *); | 127 | int, struct hisi_clock_data *); |
128 | #endif /* __HISI_CLK_H */ | 128 | #endif /* __HISI_CLK_H */ |
diff --git a/drivers/clk/hisilicon/reset.c b/drivers/clk/hisilicon/reset.c new file mode 100644 index 000000000000..6aa49c2204d0 --- /dev/null +++ b/drivers/clk/hisilicon/reset.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Hisilicon Reset Controller Driver | ||
3 | * | ||
4 | * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/io.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/reset-controller.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include "reset.h" | ||
26 | |||
27 | #define HISI_RESET_BIT_MASK 0x1f | ||
28 | #define HISI_RESET_OFFSET_SHIFT 8 | ||
29 | #define HISI_RESET_OFFSET_MASK 0xffff00 | ||
30 | |||
31 | struct hisi_reset_controller { | ||
32 | spinlock_t lock; | ||
33 | void __iomem *membase; | ||
34 | struct reset_controller_dev rcdev; | ||
35 | }; | ||
36 | |||
37 | |||
38 | #define to_hisi_reset_controller(rcdev) \ | ||
39 | container_of(rcdev, struct hisi_reset_controller, rcdev) | ||
40 | |||
41 | static int hisi_reset_of_xlate(struct reset_controller_dev *rcdev, | ||
42 | const struct of_phandle_args *reset_spec) | ||
43 | { | ||
44 | u32 offset; | ||
45 | u8 bit; | ||
46 | |||
47 | offset = (reset_spec->args[0] << HISI_RESET_OFFSET_SHIFT) | ||
48 | & HISI_RESET_OFFSET_MASK; | ||
49 | bit = reset_spec->args[1] & HISI_RESET_BIT_MASK; | ||
50 | |||
51 | return (offset | bit); | ||
52 | } | ||
53 | |||
54 | static int hisi_reset_assert(struct reset_controller_dev *rcdev, | ||
55 | unsigned long id) | ||
56 | { | ||
57 | struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev); | ||
58 | unsigned long flags; | ||
59 | u32 offset, reg; | ||
60 | u8 bit; | ||
61 | |||
62 | offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT; | ||
63 | bit = id & HISI_RESET_BIT_MASK; | ||
64 | |||
65 | spin_lock_irqsave(&rstc->lock, flags); | ||
66 | |||
67 | reg = readl(rstc->membase + offset); | ||
68 | writel(reg | BIT(bit), rstc->membase + offset); | ||
69 | |||
70 | spin_unlock_irqrestore(&rstc->lock, flags); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int hisi_reset_deassert(struct reset_controller_dev *rcdev, | ||
76 | unsigned long id) | ||
77 | { | ||
78 | struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev); | ||
79 | unsigned long flags; | ||
80 | u32 offset, reg; | ||
81 | u8 bit; | ||
82 | |||
83 | offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT; | ||
84 | bit = id & HISI_RESET_BIT_MASK; | ||
85 | |||
86 | spin_lock_irqsave(&rstc->lock, flags); | ||
87 | |||
88 | reg = readl(rstc->membase + offset); | ||
89 | writel(reg & ~BIT(bit), rstc->membase + offset); | ||
90 | |||
91 | spin_unlock_irqrestore(&rstc->lock, flags); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static const struct reset_control_ops hisi_reset_ops = { | ||
97 | .assert = hisi_reset_assert, | ||
98 | .deassert = hisi_reset_deassert, | ||
99 | }; | ||
100 | |||
101 | struct hisi_reset_controller *hisi_reset_init(struct device_node *np) | ||
102 | { | ||
103 | struct hisi_reset_controller *rstc; | ||
104 | |||
105 | rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); | ||
106 | if (!rstc) | ||
107 | return NULL; | ||
108 | |||
109 | rstc->membase = of_iomap(np, 0); | ||
110 | if (!rstc->membase) { | ||
111 | kfree(rstc); | ||
112 | return NULL; | ||
113 | } | ||
114 | |||
115 | spin_lock_init(&rstc->lock); | ||
116 | |||
117 | rstc->rcdev.owner = THIS_MODULE; | ||
118 | rstc->rcdev.ops = &hisi_reset_ops; | ||
119 | rstc->rcdev.of_node = np; | ||
120 | rstc->rcdev.of_reset_n_cells = 2; | ||
121 | rstc->rcdev.of_xlate = hisi_reset_of_xlate; | ||
122 | reset_controller_register(&rstc->rcdev); | ||
123 | |||
124 | return rstc; | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(hisi_reset_init); | ||
127 | |||
128 | void hisi_reset_exit(struct hisi_reset_controller *rstc) | ||
129 | { | ||
130 | reset_controller_unregister(&rstc->rcdev); | ||
131 | iounmap(rstc->membase); | ||
132 | kfree(rstc); | ||
133 | } | ||
134 | EXPORT_SYMBOL_GPL(hisi_reset_exit); | ||
diff --git a/drivers/clk/hisilicon/reset.h b/drivers/clk/hisilicon/reset.h new file mode 100644 index 000000000000..677d773ed27c --- /dev/null +++ b/drivers/clk/hisilicon/reset.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 HiSilicon Technologies Co., Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #ifndef __HISI_RESET_H | ||
19 | #define __HISI_RESET_H | ||
20 | |||
21 | struct device_node; | ||
22 | struct hisi_reset_controller; | ||
23 | |||
24 | #ifdef CONFIG_RESET_CONTROLLER | ||
25 | struct hisi_reset_controller *hisi_reset_init(struct device_node *np); | ||
26 | void hisi_reset_exit(struct hisi_reset_controller *rstc); | ||
27 | #else | ||
28 | static inline hisi_reset_controller *hisi_reset_init(struct device_node *np) | ||
29 | { | ||
30 | return 0; | ||
31 | } | ||
32 | static inline void hisi_reset_exit(struct hisi_reset_controller *rstc) | ||
33 | {} | ||
34 | #endif | ||
35 | |||
36 | #endif /* __HISI_RESET_H */ | ||
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index 8935bff99fe7..db44a198a0d9 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c | |||
@@ -31,6 +31,7 @@ struct clk_gate2 { | |||
31 | struct clk_hw hw; | 31 | struct clk_hw hw; |
32 | void __iomem *reg; | 32 | void __iomem *reg; |
33 | u8 bit_idx; | 33 | u8 bit_idx; |
34 | u8 cgr_val; | ||
34 | u8 flags; | 35 | u8 flags; |
35 | spinlock_t *lock; | 36 | spinlock_t *lock; |
36 | unsigned int *share_count; | 37 | unsigned int *share_count; |
@@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw) | |||
50 | goto out; | 51 | goto out; |
51 | 52 | ||
52 | reg = readl(gate->reg); | 53 | reg = readl(gate->reg); |
53 | reg |= 3 << gate->bit_idx; | 54 | reg &= ~(3 << gate->bit_idx); |
55 | reg |= gate->cgr_val << gate->bit_idx; | ||
54 | writel(reg, gate->reg); | 56 | writel(reg, gate->reg); |
55 | 57 | ||
56 | out: | 58 | out: |
@@ -125,7 +127,7 @@ static struct clk_ops clk_gate2_ops = { | |||
125 | 127 | ||
126 | struct clk *clk_register_gate2(struct device *dev, const char *name, | 128 | struct clk *clk_register_gate2(struct device *dev, const char *name, |
127 | const char *parent_name, unsigned long flags, | 129 | const char *parent_name, unsigned long flags, |
128 | void __iomem *reg, u8 bit_idx, | 130 | void __iomem *reg, u8 bit_idx, u8 cgr_val, |
129 | u8 clk_gate2_flags, spinlock_t *lock, | 131 | u8 clk_gate2_flags, spinlock_t *lock, |
130 | unsigned int *share_count) | 132 | unsigned int *share_count) |
131 | { | 133 | { |
@@ -140,6 +142,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name, | |||
140 | /* struct clk_gate2 assignments */ | 142 | /* struct clk_gate2 assignments */ |
141 | gate->reg = reg; | 143 | gate->reg = reg; |
142 | gate->bit_idx = bit_idx; | 144 | gate->bit_idx = bit_idx; |
145 | gate->cgr_val = cgr_val; | ||
143 | gate->flags = clk_gate2_flags; | 146 | gate->flags = clk_gate2_flags; |
144 | gate->lock = lock; | 147 | gate->lock = lock; |
145 | gate->share_count = share_count; | 148 | gate->share_count = share_count; |
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c index a71d24cb4c06..b0978d3b83e2 100644 --- a/drivers/clk/imx/clk-imx35.c +++ b/drivers/clk/imx/clk-imx35.c | |||
@@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll", "arm"}; | |||
66 | static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"}; | 66 | static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"}; |
67 | 67 | ||
68 | enum mx35_clks { | 68 | enum mx35_clks { |
69 | ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, | 69 | ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg, |
70 | arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel, | 70 | arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel, |
71 | esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre, | 71 | esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre, |
72 | spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre, | 72 | spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre, |
@@ -79,7 +79,7 @@ enum mx35_clks { | |||
79 | rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate, | 79 | rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate, |
80 | ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate, | 80 | ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate, |
81 | wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate, | 81 | wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate, |
82 | gpu2d_gate, clk_max | 82 | gpu2d_gate, ckil, clk_max |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static struct clk *clk[clk_max]; | 85 | static struct clk *clk[clk_max]; |
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index fea125eb4330..97e742a8be17 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c | |||
@@ -134,6 +134,8 @@ static u32 share_count_esai; | |||
134 | static u32 share_count_ssi1; | 134 | static u32 share_count_ssi1; |
135 | static u32 share_count_ssi2; | 135 | static u32 share_count_ssi2; |
136 | static u32 share_count_ssi3; | 136 | static u32 share_count_ssi3; |
137 | static u32 share_count_sai1; | ||
138 | static u32 share_count_sai2; | ||
137 | 139 | ||
138 | static struct clk ** const uart_clks[] __initconst = { | 140 | static struct clk ** const uart_clks[] __initconst = { |
139 | &clks[IMX6SX_CLK_UART_IPG], | 141 | &clks[IMX6SX_CLK_UART_IPG], |
@@ -469,10 +471,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) | |||
469 | clks[IMX6SX_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); | 471 | clks[IMX6SX_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3); |
470 | clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); | 472 | clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); |
471 | clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26); | 473 | clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26); |
472 | clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2("sai1_ipg", "ipg", base + 0x7c, 28); | 474 | clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2_shared("sai1_ipg", "ipg", base + 0x7c, 28, &share_count_sai1); |
473 | clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2("sai2_ipg", "ipg", base + 0x7c, 30); | 475 | clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2_shared("sai2_ipg", "ipg", base + 0x7c, 30, &share_count_sai2); |
474 | clks[IMX6SX_CLK_SAI1] = imx_clk_gate2("sai1", "ssi1_podf", base + 0x7c, 28); | 476 | clks[IMX6SX_CLK_SAI1] = imx_clk_gate2_shared("sai1", "ssi1_podf", base + 0x7c, 28, &share_count_sai1); |
475 | clks[IMX6SX_CLK_SAI2] = imx_clk_gate2("sai2", "ssi2_podf", base + 0x7c, 30); | 477 | clks[IMX6SX_CLK_SAI2] = imx_clk_gate2_shared("sai2", "ssi2_podf", base + 0x7c, 30, &share_count_sai2); |
476 | 478 | ||
477 | /* CCGR6 */ | 479 | /* CCGR6 */ |
478 | clks[IMX6SX_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); | 480 | clks[IMX6SX_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); |
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index fbb6a8c8653d..522996800d5b 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c | |||
@@ -56,7 +56,7 @@ static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk", | |||
56 | "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk", | 56 | "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk", |
57 | "pll_audio_main_clk", }; | 57 | "pll_audio_main_clk", }; |
58 | 58 | ||
59 | static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_135m_clk", | 59 | static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk", |
60 | "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", | 60 | "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", |
61 | "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk", | 61 | "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk", |
62 | "pll_video_main_clk", }; | 62 | "pll_video_main_clk", }; |
@@ -342,7 +342,7 @@ static const char *clko1_sel[] = { "osc", "pll_sys_main_clk", | |||
342 | 342 | ||
343 | static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk", | 343 | static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk", |
344 | "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk", | 344 | "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk", |
345 | "pll_audio_main_clk", "pll_video_main_clk", "osc_32k_clk", }; | 345 | "pll_audio_main_clk", "pll_video_main_clk", "ckil", }; |
346 | 346 | ||
347 | static const char *lvds1_sel[] = { "pll_arm_main_clk", | 347 | static const char *lvds1_sel[] = { "pll_arm_main_clk", |
348 | "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk", | 348 | "pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk", |
@@ -382,6 +382,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) | |||
382 | 382 | ||
383 | clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0); | 383 | clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0); |
384 | clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc"); | 384 | clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc"); |
385 | clks[IMX7D_CKIL] = of_clk_get_by_name(ccm_node, "ckil"); | ||
385 | 386 | ||
386 | np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop"); | 387 | np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop"); |
387 | base = of_iomap(np, 0); | 388 | base = of_iomap(np, 0); |
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index c05c43d56a94..4826b3c9e19e 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c | |||
@@ -44,6 +44,7 @@ struct clk_pllv3 { | |||
44 | u32 powerdown; | 44 | u32 powerdown; |
45 | u32 div_mask; | 45 | u32 div_mask; |
46 | u32 div_shift; | 46 | u32 div_shift; |
47 | unsigned long ref_clock; | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) | 50 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) |
@@ -286,7 +287,9 @@ static const struct clk_ops clk_pllv3_av_ops = { | |||
286 | static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, | 287 | static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, |
287 | unsigned long parent_rate) | 288 | unsigned long parent_rate) |
288 | { | 289 | { |
289 | return 500000000; | 290 | struct clk_pllv3 *pll = to_clk_pllv3(hw); |
291 | |||
292 | return pll->ref_clock; | ||
290 | } | 293 | } |
291 | 294 | ||
292 | static const struct clk_ops clk_pllv3_enet_ops = { | 295 | static const struct clk_ops clk_pllv3_enet_ops = { |
@@ -326,7 +329,11 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, | |||
326 | break; | 329 | break; |
327 | case IMX_PLLV3_ENET_IMX7: | 330 | case IMX_PLLV3_ENET_IMX7: |
328 | pll->powerdown = IMX7_ENET_PLL_POWER; | 331 | pll->powerdown = IMX7_ENET_PLL_POWER; |
332 | pll->ref_clock = 1000000000; | ||
333 | ops = &clk_pllv3_enet_ops; | ||
334 | break; | ||
329 | case IMX_PLLV3_ENET: | 335 | case IMX_PLLV3_ENET: |
336 | pll->ref_clock = 500000000; | ||
330 | ops = &clk_pllv3_enet_ops; | 337 | ops = &clk_pllv3_enet_ops; |
331 | break; | 338 | break; |
332 | default: | 339 | default: |
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 0a94d9661d91..3a1f24475ee4 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/of_address.h> | 11 | #include <linux/of_address.h> |
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/syscore_ops.h> | ||
13 | #include <dt-bindings/clock/vf610-clock.h> | 14 | #include <dt-bindings/clock/vf610-clock.h> |
14 | 15 | ||
15 | #include "clk.h" | 16 | #include "clk.h" |
@@ -40,6 +41,7 @@ | |||
40 | #define CCM_CCGR9 (ccm_base + 0x64) | 41 | #define CCM_CCGR9 (ccm_base + 0x64) |
41 | #define CCM_CCGR10 (ccm_base + 0x68) | 42 | #define CCM_CCGR10 (ccm_base + 0x68) |
42 | #define CCM_CCGR11 (ccm_base + 0x6c) | 43 | #define CCM_CCGR11 (ccm_base + 0x6c) |
44 | #define CCM_CCGRx(x) (CCM_CCGR0 + (x) * 4) | ||
43 | #define CCM_CMEOR0 (ccm_base + 0x70) | 45 | #define CCM_CMEOR0 (ccm_base + 0x70) |
44 | #define CCM_CMEOR1 (ccm_base + 0x74) | 46 | #define CCM_CMEOR1 (ccm_base + 0x74) |
45 | #define CCM_CMEOR2 (ccm_base + 0x78) | 47 | #define CCM_CMEOR2 (ccm_base + 0x78) |
@@ -115,10 +117,19 @@ static struct clk_div_table pll4_audio_div_table[] = { | |||
115 | static struct clk *clk[VF610_CLK_END]; | 117 | static struct clk *clk[VF610_CLK_END]; |
116 | static struct clk_onecell_data clk_data; | 118 | static struct clk_onecell_data clk_data; |
117 | 119 | ||
120 | static u32 cscmr1; | ||
121 | static u32 cscmr2; | ||
122 | static u32 cscdr1; | ||
123 | static u32 cscdr2; | ||
124 | static u32 cscdr3; | ||
125 | static u32 ccgr[12]; | ||
126 | |||
118 | static unsigned int const clks_init_on[] __initconst = { | 127 | static unsigned int const clks_init_on[] __initconst = { |
119 | VF610_CLK_SYS_BUS, | 128 | VF610_CLK_SYS_BUS, |
120 | VF610_CLK_DDR_SEL, | 129 | VF610_CLK_DDR_SEL, |
121 | VF610_CLK_DAP, | 130 | VF610_CLK_DAP, |
131 | VF610_CLK_DDRMC, | ||
132 | VF610_CLK_WKPU, | ||
122 | }; | 133 | }; |
123 | 134 | ||
124 | static struct clk * __init vf610_get_fixed_clock( | 135 | static struct clk * __init vf610_get_fixed_clock( |
@@ -132,6 +143,43 @@ static struct clk * __init vf610_get_fixed_clock( | |||
132 | return clk; | 143 | return clk; |
133 | }; | 144 | }; |
134 | 145 | ||
146 | static int vf610_clk_suspend(void) | ||
147 | { | ||
148 | int i; | ||
149 | |||
150 | cscmr1 = readl_relaxed(CCM_CSCMR1); | ||
151 | cscmr2 = readl_relaxed(CCM_CSCMR2); | ||
152 | |||
153 | cscdr1 = readl_relaxed(CCM_CSCDR1); | ||
154 | cscdr2 = readl_relaxed(CCM_CSCDR2); | ||
155 | cscdr3 = readl_relaxed(CCM_CSCDR3); | ||
156 | |||
157 | for (i = 0; i < 12; i++) | ||
158 | ccgr[i] = readl_relaxed(CCM_CCGRx(i)); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void vf610_clk_resume(void) | ||
164 | { | ||
165 | int i; | ||
166 | |||
167 | writel_relaxed(cscmr1, CCM_CSCMR1); | ||
168 | writel_relaxed(cscmr2, CCM_CSCMR2); | ||
169 | |||
170 | writel_relaxed(cscdr1, CCM_CSCDR1); | ||
171 | writel_relaxed(cscdr2, CCM_CSCDR2); | ||
172 | writel_relaxed(cscdr3, CCM_CSCDR3); | ||
173 | |||
174 | for (i = 0; i < 12; i++) | ||
175 | writel_relaxed(ccgr[i], CCM_CCGRx(i)); | ||
176 | } | ||
177 | |||
178 | static struct syscore_ops vf610_clk_syscore_ops = { | ||
179 | .suspend = vf610_clk_suspend, | ||
180 | .resume = vf610_clk_resume, | ||
181 | }; | ||
182 | |||
135 | static void __init vf610_clocks_init(struct device_node *ccm_node) | 183 | static void __init vf610_clocks_init(struct device_node *ccm_node) |
136 | { | 184 | { |
137 | struct device_node *np; | 185 | struct device_node *np; |
@@ -233,6 +281,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) | |||
233 | clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock); | 281 | clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock); |
234 | clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1); | 282 | clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1); |
235 | 283 | ||
284 | clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2); | ||
285 | clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(10), 0x2); | ||
286 | |||
236 | clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6); | 287 | clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6); |
237 | clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6); | 288 | clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6); |
238 | 289 | ||
@@ -321,11 +372,14 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) | |||
321 | clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2); | 372 | clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2); |
322 | clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19); | 373 | clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19); |
323 | clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3); | 374 | clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3); |
324 | clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8)); | 375 | clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", CCM_CCGR3, CCM_CCGRx_CGn(8)); |
325 | clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2); | 376 | clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2); |
326 | clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23); | 377 | clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23); |
327 | clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); | 378 | clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3); |
328 | clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8)); | 379 | clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8)); |
380 | |||
381 | clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13)); | ||
382 | clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13)); | ||
329 | 383 | ||
330 | clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4); | 384 | clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4); |
331 | clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30); | 385 | clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30); |
@@ -409,6 +463,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) | |||
409 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | 463 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) |
410 | clk_prepare_enable(clk[clks_init_on[i]]); | 464 | clk_prepare_enable(clk[clks_init_on[i]]); |
411 | 465 | ||
466 | register_syscore_ops(&vf610_clk_syscore_ops); | ||
467 | |||
412 | /* Add the clocks to provider list */ | 468 | /* Add the clocks to provider list */ |
413 | clk_data.clks = clk; | 469 | clk_data.clks = clk; |
414 | clk_data.clk_num = ARRAY_SIZE(clk); | 470 | clk_data.clk_num = ARRAY_SIZE(clk); |
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index d942f5748d08..508d0fad84cf 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h | |||
@@ -41,7 +41,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, | |||
41 | 41 | ||
42 | struct clk *clk_register_gate2(struct device *dev, const char *name, | 42 | struct clk *clk_register_gate2(struct device *dev, const char *name, |
43 | const char *parent_name, unsigned long flags, | 43 | const char *parent_name, unsigned long flags, |
44 | void __iomem *reg, u8 bit_idx, | 44 | void __iomem *reg, u8 bit_idx, u8 cgr_val, |
45 | u8 clk_gate_flags, spinlock_t *lock, | 45 | u8 clk_gate_flags, spinlock_t *lock, |
46 | unsigned int *share_count); | 46 | unsigned int *share_count); |
47 | 47 | ||
@@ -55,7 +55,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent, | |||
55 | void __iomem *reg, u8 shift) | 55 | void __iomem *reg, u8 shift) |
56 | { | 56 | { |
57 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | 57 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, |
58 | shift, 0, &imx_ccm_lock, NULL); | 58 | shift, 0x3, 0, &imx_ccm_lock, NULL); |
59 | } | 59 | } |
60 | 60 | ||
61 | static inline struct clk *imx_clk_gate2_shared(const char *name, | 61 | static inline struct clk *imx_clk_gate2_shared(const char *name, |
@@ -63,7 +63,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name, | |||
63 | unsigned int *share_count) | 63 | unsigned int *share_count) |
64 | { | 64 | { |
65 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | 65 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, |
66 | shift, 0, &imx_ccm_lock, share_count); | 66 | shift, 0x3, 0, &imx_ccm_lock, share_count); |
67 | } | ||
68 | |||
69 | static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent, | ||
70 | void __iomem *reg, u8 shift, u8 cgr_val) | ||
71 | { | ||
72 | return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, | ||
73 | shift, cgr_val, 0, &imx_ccm_lock, NULL); | ||
67 | } | 74 | } |
68 | 75 | ||
69 | struct clk *imx_clk_pfd(const char *name, const char *parent_name, | 76 | struct clk *imx_clk_pfd(const char *name, const char *parent_name, |
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index 7cfb7b2a2ed6..e8248f9185f7 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c | |||
@@ -325,6 +325,7 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
325 | div = (div_reg >> clk_info->div.shift) & | 325 | div = (div_reg >> clk_info->div.shift) & |
326 | GENMASK(clk_info->div.bits - 1, 0); | 326 | GENMASK(clk_info->div.bits - 1, 0); |
327 | div += 1; | 327 | div += 1; |
328 | div *= clk_info->div.div; | ||
328 | 329 | ||
329 | rate /= div; | 330 | rate /= div; |
330 | } | 331 | } |
@@ -345,6 +346,14 @@ ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info, | |||
345 | div = min_t(unsigned, div, 1 << clk_info->div.bits); | 346 | div = min_t(unsigned, div, 1 << clk_info->div.bits); |
346 | div = max_t(unsigned, div, 1); | 347 | div = max_t(unsigned, div, 1); |
347 | 348 | ||
349 | /* | ||
350 | * If the divider value itself must be divided before being written to | ||
351 | * the divider register, we must ensure we don't have any bits set that | ||
352 | * would be lost as a result of doing so. | ||
353 | */ | ||
354 | div /= clk_info->div.div; | ||
355 | div *= clk_info->div.div; | ||
356 | |||
348 | return div; | 357 | return div; |
349 | } | 358 | } |
350 | 359 | ||
@@ -395,7 +404,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, | |||
395 | /* update the divide */ | 404 | /* update the divide */ |
396 | mask = GENMASK(clk_info->div.bits - 1, 0); | 405 | mask = GENMASK(clk_info->div.bits - 1, 0); |
397 | reg &= ~(mask << clk_info->div.shift); | 406 | reg &= ~(mask << clk_info->div.shift); |
398 | reg |= (div - 1) << clk_info->div.shift; | 407 | reg |= ((div / clk_info->div.div) - 1) << clk_info->div.shift; |
399 | 408 | ||
400 | /* clear the stop bit */ | 409 | /* clear the stop bit */ |
401 | if (clk_info->div.stop_bit != -1) | 410 | if (clk_info->div.stop_bit != -1) |
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index 99347e2b97e8..09700b2c555d 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h | |||
@@ -76,8 +76,11 @@ struct ingenic_cgu_mux_info { | |||
76 | /** | 76 | /** |
77 | * struct ingenic_cgu_div_info - information about a divider | 77 | * struct ingenic_cgu_div_info - information about a divider |
78 | * @reg: offset of the divider control register within the CGU | 78 | * @reg: offset of the divider control register within the CGU |
79 | * @shift: number of bits to shift the divide value by (ie. the index of | 79 | * @shift: number of bits to left shift the divide value by (ie. the index of |
80 | * the lowest bit of the divide value within its control register) | 80 | * the lowest bit of the divide value within its control register) |
81 | * @div: number of bits to divide the divider value by (i.e. if the | ||
82 | * effective divider value is the value written to the register | ||
83 | * multiplied by some constant) | ||
81 | * @bits: the size of the divide value in bits | 84 | * @bits: the size of the divide value in bits |
82 | * @ce_bit: the index of the change enable bit within reg, or -1 if there | 85 | * @ce_bit: the index of the change enable bit within reg, or -1 if there |
83 | * isn't one | 86 | * isn't one |
@@ -87,6 +90,7 @@ struct ingenic_cgu_mux_info { | |||
87 | struct ingenic_cgu_div_info { | 90 | struct ingenic_cgu_div_info { |
88 | unsigned reg; | 91 | unsigned reg; |
89 | u8 shift; | 92 | u8 shift; |
93 | u8 div; | ||
90 | u8 bits; | 94 | u8 bits; |
91 | s8 ce_bit; | 95 | s8 ce_bit; |
92 | s8 busy_bit; | 96 | s8 busy_bit; |
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c index 305a26c2a800..510fe7e0c8f1 100644 --- a/drivers/clk/ingenic/jz4740-cgu.c +++ b/drivers/clk/ingenic/jz4740-cgu.c | |||
@@ -90,51 +90,51 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { | |||
90 | [JZ4740_CLK_PLL_HALF] = { | 90 | [JZ4740_CLK_PLL_HALF] = { |
91 | "pll half", CGU_CLK_DIV, | 91 | "pll half", CGU_CLK_DIV, |
92 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, | 92 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, |
93 | .div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 }, | 93 | .div = { CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1 }, |
94 | }, | 94 | }, |
95 | 95 | ||
96 | [JZ4740_CLK_CCLK] = { | 96 | [JZ4740_CLK_CCLK] = { |
97 | "cclk", CGU_CLK_DIV, | 97 | "cclk", CGU_CLK_DIV, |
98 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, | 98 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, |
99 | .div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 }, | 99 | .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, |
100 | }, | 100 | }, |
101 | 101 | ||
102 | [JZ4740_CLK_HCLK] = { | 102 | [JZ4740_CLK_HCLK] = { |
103 | "hclk", CGU_CLK_DIV, | 103 | "hclk", CGU_CLK_DIV, |
104 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, | 104 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, |
105 | .div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 }, | 105 | .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, |
106 | }, | 106 | }, |
107 | 107 | ||
108 | [JZ4740_CLK_PCLK] = { | 108 | [JZ4740_CLK_PCLK] = { |
109 | "pclk", CGU_CLK_DIV, | 109 | "pclk", CGU_CLK_DIV, |
110 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, | 110 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, |
111 | .div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 }, | 111 | .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 }, |
112 | }, | 112 | }, |
113 | 113 | ||
114 | [JZ4740_CLK_MCLK] = { | 114 | [JZ4740_CLK_MCLK] = { |
115 | "mclk", CGU_CLK_DIV, | 115 | "mclk", CGU_CLK_DIV, |
116 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, | 116 | .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, |
117 | .div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 }, | 117 | .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 }, |
118 | }, | 118 | }, |
119 | 119 | ||
120 | [JZ4740_CLK_LCD] = { | 120 | [JZ4740_CLK_LCD] = { |
121 | "lcd", CGU_CLK_DIV | CGU_CLK_GATE, | 121 | "lcd", CGU_CLK_DIV | CGU_CLK_GATE, |
122 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, | 122 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, |
123 | .div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 }, | 123 | .div = { CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1 }, |
124 | .gate = { CGU_REG_CLKGR, 10 }, | 124 | .gate = { CGU_REG_CLKGR, 10 }, |
125 | }, | 125 | }, |
126 | 126 | ||
127 | [JZ4740_CLK_LCD_PCLK] = { | 127 | [JZ4740_CLK_LCD_PCLK] = { |
128 | "lcd_pclk", CGU_CLK_DIV, | 128 | "lcd_pclk", CGU_CLK_DIV, |
129 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, | 129 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, |
130 | .div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 }, | 130 | .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, |
131 | }, | 131 | }, |
132 | 132 | ||
133 | [JZ4740_CLK_I2S] = { | 133 | [JZ4740_CLK_I2S] = { |
134 | "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, | 134 | "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, |
135 | .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 }, | 135 | .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 }, |
136 | .mux = { CGU_REG_CPCCR, 31, 1 }, | 136 | .mux = { CGU_REG_CPCCR, 31, 1 }, |
137 | .div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 }, | 137 | .div = { CGU_REG_I2SCDR, 0, 1, 8, -1, -1, -1 }, |
138 | .gate = { CGU_REG_CLKGR, 6 }, | 138 | .gate = { CGU_REG_CLKGR, 6 }, |
139 | }, | 139 | }, |
140 | 140 | ||
@@ -142,21 +142,21 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { | |||
142 | "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, | 142 | "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, |
143 | .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 }, | 143 | .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 }, |
144 | .mux = { CGU_REG_SSICDR, 31, 1 }, | 144 | .mux = { CGU_REG_SSICDR, 31, 1 }, |
145 | .div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 }, | 145 | .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 }, |
146 | .gate = { CGU_REG_CLKGR, 4 }, | 146 | .gate = { CGU_REG_CLKGR, 4 }, |
147 | }, | 147 | }, |
148 | 148 | ||
149 | [JZ4740_CLK_MMC] = { | 149 | [JZ4740_CLK_MMC] = { |
150 | "mmc", CGU_CLK_DIV | CGU_CLK_GATE, | 150 | "mmc", CGU_CLK_DIV | CGU_CLK_GATE, |
151 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, | 151 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, |
152 | .div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 }, | 152 | .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 }, |
153 | .gate = { CGU_REG_CLKGR, 7 }, | 153 | .gate = { CGU_REG_CLKGR, 7 }, |
154 | }, | 154 | }, |
155 | 155 | ||
156 | [JZ4740_CLK_UHC] = { | 156 | [JZ4740_CLK_UHC] = { |
157 | "uhc", CGU_CLK_DIV | CGU_CLK_GATE, | 157 | "uhc", CGU_CLK_DIV | CGU_CLK_GATE, |
158 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, | 158 | .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, |
159 | .div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 }, | 159 | .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 }, |
160 | .gate = { CGU_REG_CLKGR, 14 }, | 160 | .gate = { CGU_REG_CLKGR, 14 }, |
161 | }, | 161 | }, |
162 | 162 | ||
@@ -164,7 +164,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { | |||
164 | "udc", CGU_CLK_MUX | CGU_CLK_DIV, | 164 | "udc", CGU_CLK_MUX | CGU_CLK_DIV, |
165 | .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 }, | 165 | .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 }, |
166 | .mux = { CGU_REG_CPCCR, 29, 1 }, | 166 | .mux = { CGU_REG_CPCCR, 29, 1 }, |
167 | .div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 }, | 167 | .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 }, |
168 | .gate = { CGU_REG_SCR, 6 }, | 168 | .gate = { CGU_REG_SCR, 6 }, |
169 | }, | 169 | }, |
170 | 170 | ||
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c index 431f962300b6..b35d6d9dd5aa 100644 --- a/drivers/clk/ingenic/jz4780-cgu.c +++ b/drivers/clk/ingenic/jz4780-cgu.c | |||
@@ -296,13 +296,13 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
296 | [JZ4780_CLK_CPU] = { | 296 | [JZ4780_CLK_CPU] = { |
297 | "cpu", CGU_CLK_DIV, | 297 | "cpu", CGU_CLK_DIV, |
298 | .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, | 298 | .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, |
299 | .div = { CGU_REG_CLOCKCONTROL, 0, 4, 22, -1, -1 }, | 299 | .div = { CGU_REG_CLOCKCONTROL, 0, 1, 4, 22, -1, -1 }, |
300 | }, | 300 | }, |
301 | 301 | ||
302 | [JZ4780_CLK_L2CACHE] = { | 302 | [JZ4780_CLK_L2CACHE] = { |
303 | "l2cache", CGU_CLK_DIV, | 303 | "l2cache", CGU_CLK_DIV, |
304 | .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, | 304 | .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, |
305 | .div = { CGU_REG_CLOCKCONTROL, 4, 4, -1, -1, -1 }, | 305 | .div = { CGU_REG_CLOCKCONTROL, 4, 1, 4, -1, -1, -1 }, |
306 | }, | 306 | }, |
307 | 307 | ||
308 | [JZ4780_CLK_AHB0] = { | 308 | [JZ4780_CLK_AHB0] = { |
@@ -310,7 +310,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
310 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 310 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
311 | JZ4780_CLK_EPLL }, | 311 | JZ4780_CLK_EPLL }, |
312 | .mux = { CGU_REG_CLOCKCONTROL, 26, 2 }, | 312 | .mux = { CGU_REG_CLOCKCONTROL, 26, 2 }, |
313 | .div = { CGU_REG_CLOCKCONTROL, 8, 4, 21, -1, -1 }, | 313 | .div = { CGU_REG_CLOCKCONTROL, 8, 1, 4, 21, -1, -1 }, |
314 | }, | 314 | }, |
315 | 315 | ||
316 | [JZ4780_CLK_AHB2PMUX] = { | 316 | [JZ4780_CLK_AHB2PMUX] = { |
@@ -323,20 +323,20 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
323 | [JZ4780_CLK_AHB2] = { | 323 | [JZ4780_CLK_AHB2] = { |
324 | "ahb2", CGU_CLK_DIV, | 324 | "ahb2", CGU_CLK_DIV, |
325 | .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 }, | 325 | .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 }, |
326 | .div = { CGU_REG_CLOCKCONTROL, 12, 4, 20, -1, -1 }, | 326 | .div = { CGU_REG_CLOCKCONTROL, 12, 1, 4, 20, -1, -1 }, |
327 | }, | 327 | }, |
328 | 328 | ||
329 | [JZ4780_CLK_PCLK] = { | 329 | [JZ4780_CLK_PCLK] = { |
330 | "pclk", CGU_CLK_DIV, | 330 | "pclk", CGU_CLK_DIV, |
331 | .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 }, | 331 | .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 }, |
332 | .div = { CGU_REG_CLOCKCONTROL, 16, 4, 20, -1, -1 }, | 332 | .div = { CGU_REG_CLOCKCONTROL, 16, 1, 4, 20, -1, -1 }, |
333 | }, | 333 | }, |
334 | 334 | ||
335 | [JZ4780_CLK_DDR] = { | 335 | [JZ4780_CLK_DDR] = { |
336 | "ddr", CGU_CLK_MUX | CGU_CLK_DIV, | 336 | "ddr", CGU_CLK_MUX | CGU_CLK_DIV, |
337 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 }, | 337 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 }, |
338 | .mux = { CGU_REG_DDRCDR, 30, 2 }, | 338 | .mux = { CGU_REG_DDRCDR, 30, 2 }, |
339 | .div = { CGU_REG_DDRCDR, 0, 4, 29, 28, 27 }, | 339 | .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, |
340 | }, | 340 | }, |
341 | 341 | ||
342 | [JZ4780_CLK_VPU] = { | 342 | [JZ4780_CLK_VPU] = { |
@@ -344,7 +344,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
344 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 344 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
345 | JZ4780_CLK_EPLL, -1 }, | 345 | JZ4780_CLK_EPLL, -1 }, |
346 | .mux = { CGU_REG_VPUCDR, 30, 2 }, | 346 | .mux = { CGU_REG_VPUCDR, 30, 2 }, |
347 | .div = { CGU_REG_VPUCDR, 0, 4, 29, 28, 27 }, | 347 | .div = { CGU_REG_VPUCDR, 0, 1, 4, 29, 28, 27 }, |
348 | .gate = { CGU_REG_CLKGR1, 2 }, | 348 | .gate = { CGU_REG_CLKGR1, 2 }, |
349 | }, | 349 | }, |
350 | 350 | ||
@@ -352,7 +352,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
352 | "i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV, | 352 | "i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV, |
353 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1, -1 }, | 353 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1, -1 }, |
354 | .mux = { CGU_REG_I2SCDR, 30, 1 }, | 354 | .mux = { CGU_REG_I2SCDR, 30, 1 }, |
355 | .div = { CGU_REG_I2SCDR, 0, 8, 29, 28, 27 }, | 355 | .div = { CGU_REG_I2SCDR, 0, 1, 8, 29, 28, 27 }, |
356 | }, | 356 | }, |
357 | 357 | ||
358 | [JZ4780_CLK_I2S] = { | 358 | [JZ4780_CLK_I2S] = { |
@@ -366,7 +366,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
366 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 366 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
367 | JZ4780_CLK_VPLL, -1 }, | 367 | JZ4780_CLK_VPLL, -1 }, |
368 | .mux = { CGU_REG_LP0CDR, 30, 2 }, | 368 | .mux = { CGU_REG_LP0CDR, 30, 2 }, |
369 | .div = { CGU_REG_LP0CDR, 0, 8, 28, 27, 26 }, | 369 | .div = { CGU_REG_LP0CDR, 0, 1, 8, 28, 27, 26 }, |
370 | }, | 370 | }, |
371 | 371 | ||
372 | [JZ4780_CLK_LCD1PIXCLK] = { | 372 | [JZ4780_CLK_LCD1PIXCLK] = { |
@@ -374,7 +374,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
374 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 374 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
375 | JZ4780_CLK_VPLL, -1 }, | 375 | JZ4780_CLK_VPLL, -1 }, |
376 | .mux = { CGU_REG_LP1CDR, 30, 2 }, | 376 | .mux = { CGU_REG_LP1CDR, 30, 2 }, |
377 | .div = { CGU_REG_LP1CDR, 0, 8, 28, 27, 26 }, | 377 | .div = { CGU_REG_LP1CDR, 0, 1, 8, 28, 27, 26 }, |
378 | }, | 378 | }, |
379 | 379 | ||
380 | [JZ4780_CLK_MSCMUX] = { | 380 | [JZ4780_CLK_MSCMUX] = { |
@@ -386,21 +386,21 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
386 | [JZ4780_CLK_MSC0] = { | 386 | [JZ4780_CLK_MSC0] = { |
387 | "msc0", CGU_CLK_DIV | CGU_CLK_GATE, | 387 | "msc0", CGU_CLK_DIV | CGU_CLK_GATE, |
388 | .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, | 388 | .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, |
389 | .div = { CGU_REG_MSC0CDR, 0, 8, 29, 28, 27 }, | 389 | .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 }, |
390 | .gate = { CGU_REG_CLKGR0, 3 }, | 390 | .gate = { CGU_REG_CLKGR0, 3 }, |
391 | }, | 391 | }, |
392 | 392 | ||
393 | [JZ4780_CLK_MSC1] = { | 393 | [JZ4780_CLK_MSC1] = { |
394 | "msc1", CGU_CLK_DIV | CGU_CLK_GATE, | 394 | "msc1", CGU_CLK_DIV | CGU_CLK_GATE, |
395 | .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, | 395 | .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, |
396 | .div = { CGU_REG_MSC1CDR, 0, 8, 29, 28, 27 }, | 396 | .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 }, |
397 | .gate = { CGU_REG_CLKGR0, 11 }, | 397 | .gate = { CGU_REG_CLKGR0, 11 }, |
398 | }, | 398 | }, |
399 | 399 | ||
400 | [JZ4780_CLK_MSC2] = { | 400 | [JZ4780_CLK_MSC2] = { |
401 | "msc2", CGU_CLK_DIV | CGU_CLK_GATE, | 401 | "msc2", CGU_CLK_DIV | CGU_CLK_GATE, |
402 | .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, | 402 | .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 }, |
403 | .div = { CGU_REG_MSC2CDR, 0, 8, 29, 28, 27 }, | 403 | .div = { CGU_REG_MSC2CDR, 0, 2, 8, 29, 28, 27 }, |
404 | .gate = { CGU_REG_CLKGR0, 12 }, | 404 | .gate = { CGU_REG_CLKGR0, 12 }, |
405 | }, | 405 | }, |
406 | 406 | ||
@@ -409,7 +409,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
409 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 409 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
410 | JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY }, | 410 | JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY }, |
411 | .mux = { CGU_REG_UHCCDR, 30, 2 }, | 411 | .mux = { CGU_REG_UHCCDR, 30, 2 }, |
412 | .div = { CGU_REG_UHCCDR, 0, 8, 29, 28, 27 }, | 412 | .div = { CGU_REG_UHCCDR, 0, 1, 8, 29, 28, 27 }, |
413 | .gate = { CGU_REG_CLKGR0, 24 }, | 413 | .gate = { CGU_REG_CLKGR0, 24 }, |
414 | }, | 414 | }, |
415 | 415 | ||
@@ -417,7 +417,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
417 | "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, | 417 | "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, |
418 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 }, | 418 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 }, |
419 | .mux = { CGU_REG_SSICDR, 30, 1 }, | 419 | .mux = { CGU_REG_SSICDR, 30, 1 }, |
420 | .div = { CGU_REG_SSICDR, 0, 8, 29, 28, 27 }, | 420 | .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 }, |
421 | }, | 421 | }, |
422 | 422 | ||
423 | [JZ4780_CLK_SSI] = { | 423 | [JZ4780_CLK_SSI] = { |
@@ -430,7 +430,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
430 | "cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV, | 430 | "cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV, |
431 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 }, | 431 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 }, |
432 | .mux = { CGU_REG_CIMCDR, 31, 1 }, | 432 | .mux = { CGU_REG_CIMCDR, 31, 1 }, |
433 | .div = { CGU_REG_CIMCDR, 0, 8, 30, 29, 28 }, | 433 | .div = { CGU_REG_CIMCDR, 0, 1, 8, 30, 29, 28 }, |
434 | }, | 434 | }, |
435 | 435 | ||
436 | [JZ4780_CLK_PCMPLL] = { | 436 | [JZ4780_CLK_PCMPLL] = { |
@@ -438,7 +438,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
438 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 438 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
439 | JZ4780_CLK_EPLL, JZ4780_CLK_VPLL }, | 439 | JZ4780_CLK_EPLL, JZ4780_CLK_VPLL }, |
440 | .mux = { CGU_REG_PCMCDR, 29, 2 }, | 440 | .mux = { CGU_REG_PCMCDR, 29, 2 }, |
441 | .div = { CGU_REG_PCMCDR, 0, 8, 28, 27, 26 }, | 441 | .div = { CGU_REG_PCMCDR, 0, 1, 8, 28, 27, 26 }, |
442 | }, | 442 | }, |
443 | 443 | ||
444 | [JZ4780_CLK_PCM] = { | 444 | [JZ4780_CLK_PCM] = { |
@@ -453,7 +453,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
453 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 453 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
454 | JZ4780_CLK_EPLL }, | 454 | JZ4780_CLK_EPLL }, |
455 | .mux = { CGU_REG_GPUCDR, 30, 2 }, | 455 | .mux = { CGU_REG_GPUCDR, 30, 2 }, |
456 | .div = { CGU_REG_GPUCDR, 0, 4, 29, 28, 27 }, | 456 | .div = { CGU_REG_GPUCDR, 0, 1, 4, 29, 28, 27 }, |
457 | .gate = { CGU_REG_CLKGR1, 4 }, | 457 | .gate = { CGU_REG_CLKGR1, 4 }, |
458 | }, | 458 | }, |
459 | 459 | ||
@@ -462,7 +462,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
462 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 462 | .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
463 | JZ4780_CLK_VPLL, -1 }, | 463 | JZ4780_CLK_VPLL, -1 }, |
464 | .mux = { CGU_REG_HDMICDR, 30, 2 }, | 464 | .mux = { CGU_REG_HDMICDR, 30, 2 }, |
465 | .div = { CGU_REG_HDMICDR, 0, 8, 29, 28, 26 }, | 465 | .div = { CGU_REG_HDMICDR, 0, 1, 8, 29, 28, 26 }, |
466 | .gate = { CGU_REG_CLKGR1, 9 }, | 466 | .gate = { CGU_REG_CLKGR1, 9 }, |
467 | }, | 467 | }, |
468 | 468 | ||
@@ -471,7 +471,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { | |||
471 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, | 471 | .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, |
472 | JZ4780_CLK_EPLL }, | 472 | JZ4780_CLK_EPLL }, |
473 | .mux = { CGU_REG_BCHCDR, 30, 2 }, | 473 | .mux = { CGU_REG_BCHCDR, 30, 2 }, |
474 | .div = { CGU_REG_BCHCDR, 0, 4, 29, 28, 27 }, | 474 | .div = { CGU_REG_BCHCDR, 0, 1, 4, 29, 28, 27 }, |
475 | .gate = { CGU_REG_CLKGR0, 1 }, | 475 | .gate = { CGU_REG_CLKGR0, 1 }, |
476 | }, | 476 | }, |
477 | 477 | ||
diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 61f6d55c4ac7..4d057b3e21b2 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c | |||
@@ -141,11 +141,11 @@ static const struct composite_conf mali_conf __initconst = { | |||
141 | }; | 141 | }; |
142 | 142 | ||
143 | static const struct clk_conf meson8b_xtal_conf __initconst = | 143 | static const struct clk_conf meson8b_xtal_conf __initconst = |
144 | FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", | 144 | FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", 0, |
145 | CLK_IS_ROOT, PARM(0x00, 4, 7)); | 145 | PARM(0x00, 4, 7)); |
146 | 146 | ||
147 | static const struct clk_conf meson8b_clk_confs[] __initconst = { | 147 | static const struct clk_conf meson8b_clk_confs[] __initconst = { |
148 | FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0), | 148 | FIXED_RATE(CLKID_ZERO, "zero", 0, 0), |
149 | PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll", | 149 | PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll", |
150 | p_xtal, 0, &pll_confs), | 150 | p_xtal, 0, &pll_confs), |
151 | PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll", | 151 | PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll", |
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c index 38931dbd1eff..383f6a4f64f0 100644 --- a/drivers/clk/mmp/clk-mmp2.c +++ b/drivers/clk/mmp/clk-mmp2.c | |||
@@ -99,23 +99,19 @@ void __init mmp2_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, | |||
99 | return; | 99 | return; |
100 | } | 100 | } |
101 | 101 | ||
102 | clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); | 102 | clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200); |
103 | clk_register_clkdev(clk, "clk32", NULL); | 103 | clk_register_clkdev(clk, "clk32", NULL); |
104 | 104 | ||
105 | vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, | 105 | vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000); |
106 | 26000000); | ||
107 | clk_register_clkdev(vctcxo, "vctcxo", NULL); | 106 | clk_register_clkdev(vctcxo, "vctcxo", NULL); |
108 | 107 | ||
109 | clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, | 108 | clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 800000000); |
110 | 800000000); | ||
111 | clk_register_clkdev(clk, "pll1", NULL); | 109 | clk_register_clkdev(clk, "pll1", NULL); |
112 | 110 | ||
113 | clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, CLK_IS_ROOT, | 111 | clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, 0, 480000000); |
114 | 480000000); | ||
115 | clk_register_clkdev(clk, "usb_pll", NULL); | 112 | clk_register_clkdev(clk, "usb_pll", NULL); |
116 | 113 | ||
117 | clk = clk_register_fixed_rate(NULL, "pll2", NULL, CLK_IS_ROOT, | 114 | clk = clk_register_fixed_rate(NULL, "pll2", NULL, 0, 960000000); |
118 | 960000000); | ||
119 | clk_register_clkdev(clk, "pll2", NULL); | 115 | clk_register_clkdev(clk, "pll2", NULL); |
120 | 116 | ||
121 | clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", | 117 | clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", |
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index 251533d87c65..3a51fff1b0e7 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c | |||
@@ -63,11 +63,11 @@ struct mmp2_clk_unit { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | 65 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { |
66 | {MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, | 66 | {MMP2_CLK_CLK32, "clk32", NULL, 0, 32768}, |
67 | {MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | 67 | {MMP2_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000}, |
68 | {MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 800000000}, | 68 | {MMP2_CLK_PLL1, "pll1", NULL, 0, 800000000}, |
69 | {MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 960000000}, | 69 | {MMP2_CLK_PLL2, "pll2", NULL, 0, 960000000}, |
70 | {MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, | 70 | {MMP2_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000}, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | 73 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { |
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c index 64eaf4141c69..87f2317b2a00 100644 --- a/drivers/clk/mmp/clk-of-pxa168.c +++ b/drivers/clk/mmp/clk-of-pxa168.c | |||
@@ -56,10 +56,10 @@ struct pxa168_clk_unit { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | 58 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { |
59 | {PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, | 59 | {PXA168_CLK_CLK32, "clk32", NULL, 0, 32768}, |
60 | {PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | 60 | {PXA168_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000}, |
61 | {PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, | 61 | {PXA168_CLK_PLL1, "pll1", NULL, 0, 624000000}, |
62 | {PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, | 62 | {PXA168_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000}, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | 65 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { |
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c index 433a5ae1eae0..e478ff44e170 100644 --- a/drivers/clk/mmp/clk-of-pxa1928.c +++ b/drivers/clk/mmp/clk-of-pxa1928.c | |||
@@ -34,12 +34,12 @@ struct pxa1928_clk_unit { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | 36 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { |
37 | {0, "clk32", NULL, CLK_IS_ROOT, 32768}, | 37 | {0, "clk32", NULL, 0, 32768}, |
38 | {0, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | 38 | {0, "vctcxo", NULL, 0, 26000000}, |
39 | {0, "pll1_624", NULL, CLK_IS_ROOT, 624000000}, | 39 | {0, "pll1_624", NULL, 0, 624000000}, |
40 | {0, "pll5p", NULL, CLK_IS_ROOT, 832000000}, | 40 | {0, "pll5p", NULL, 0, 832000000}, |
41 | {0, "pll5", NULL, CLK_IS_ROOT, 1248000000}, | 41 | {0, "pll5", NULL, 0, 1248000000}, |
42 | {0, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, | 42 | {0, "usb_pll", NULL, 0, 480000000}, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | 45 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { |
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c index 13d6173326a4..e22a67f76d93 100644 --- a/drivers/clk/mmp/clk-of-pxa910.c +++ b/drivers/clk/mmp/clk-of-pxa910.c | |||
@@ -56,10 +56,10 @@ struct pxa910_clk_unit { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { | 58 | static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = { |
59 | {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768}, | 59 | {PXA910_CLK_CLK32, "clk32", NULL, 0, 32768}, |
60 | {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000}, | 60 | {PXA910_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000}, |
61 | {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000}, | 61 | {PXA910_CLK_PLL1, "pll1", NULL, 0, 624000000}, |
62 | {PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000}, | 62 | {PXA910_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000}, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { | 65 | static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = { |
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c index 0dd83fb950c9..a9ef9209532a 100644 --- a/drivers/clk/mmp/clk-pxa168.c +++ b/drivers/clk/mmp/clk-pxa168.c | |||
@@ -92,15 +92,13 @@ void __init pxa168_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, | |||
92 | return; | 92 | return; |
93 | } | 93 | } |
94 | 94 | ||
95 | clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); | 95 | clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200); |
96 | clk_register_clkdev(clk, "clk32", NULL); | 96 | clk_register_clkdev(clk, "clk32", NULL); |
97 | 97 | ||
98 | clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, | 98 | clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000); |
99 | 26000000); | ||
100 | clk_register_clkdev(clk, "vctcxo", NULL); | 99 | clk_register_clkdev(clk, "vctcxo", NULL); |
101 | 100 | ||
102 | clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, | 101 | clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 624000000); |
103 | 624000000); | ||
104 | clk_register_clkdev(clk, "pll1", NULL); | 102 | clk_register_clkdev(clk, "pll1", NULL); |
105 | 103 | ||
106 | clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", | 104 | clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", |
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c index e1d2ce22cdf1..a520cf7702a1 100644 --- a/drivers/clk/mmp/clk-pxa910.c +++ b/drivers/clk/mmp/clk-pxa910.c | |||
@@ -97,15 +97,13 @@ void __init pxa910_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys, | |||
97 | return; | 97 | return; |
98 | } | 98 | } |
99 | 99 | ||
100 | clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200); | 100 | clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200); |
101 | clk_register_clkdev(clk, "clk32", NULL); | 101 | clk_register_clkdev(clk, "clk32", NULL); |
102 | 102 | ||
103 | clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT, | 103 | clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000); |
104 | 26000000); | ||
105 | clk_register_clkdev(clk, "vctcxo", NULL); | 104 | clk_register_clkdev(clk, "vctcxo", NULL); |
106 | 105 | ||
107 | clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT, | 106 | clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 624000000); |
108 | 624000000); | ||
109 | clk_register_clkdev(clk, "pll1", NULL); | 107 | clk_register_clkdev(clk, "pll1", NULL); |
110 | 108 | ||
111 | clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", | 109 | clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1", |
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig index eaee8f099c8c..3165da77d525 100644 --- a/drivers/clk/mvebu/Kconfig +++ b/drivers/clk/mvebu/Kconfig | |||
@@ -29,6 +29,12 @@ config ARMADA_XP_CLK | |||
29 | select MVEBU_CLK_COMMON | 29 | select MVEBU_CLK_COMMON |
30 | select MVEBU_CLK_CPU | 30 | select MVEBU_CLK_CPU |
31 | 31 | ||
32 | config ARMADA_AP806_SYSCON | ||
33 | bool | ||
34 | |||
35 | config ARMADA_CP110_SYSCON | ||
36 | bool | ||
37 | |||
32 | config DOVE_CLK | 38 | config DOVE_CLK |
33 | bool | 39 | bool |
34 | select MVEBU_CLK_COMMON | 40 | select MVEBU_CLK_COMMON |
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile index 8866115486f7..7172ef65693d 100644 --- a/drivers/clk/mvebu/Makefile +++ b/drivers/clk/mvebu/Makefile | |||
@@ -7,6 +7,8 @@ obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o | |||
7 | obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o | 7 | obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o |
8 | obj-$(CONFIG_ARMADA_39X_CLK) += armada-39x.o | 8 | obj-$(CONFIG_ARMADA_39X_CLK) += armada-39x.o |
9 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o | 9 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o |
10 | obj-$(CONFIG_ARMADA_AP806_SYSCON) += ap806-system-controller.o | ||
11 | obj-$(CONFIG_ARMADA_CP110_SYSCON) += cp110-system-controller.o | ||
10 | obj-$(CONFIG_DOVE_CLK) += dove.o dove-divider.o | 12 | obj-$(CONFIG_DOVE_CLK) += dove.o dove-divider.o |
11 | obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o | 13 | obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o |
12 | obj-$(CONFIG_ORION_CLK) += orion.o | 14 | obj-$(CONFIG_ORION_CLK) += orion.o |
diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c new file mode 100644 index 000000000000..02023baf86c9 --- /dev/null +++ b/drivers/clk/mvebu/ap806-system-controller.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Marvell Armada AP806 System Controller | ||
3 | * | ||
4 | * Copyright (C) 2016 Marvell | ||
5 | * | ||
6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) "ap806-system-controller: " fmt | ||
14 | |||
15 | #include <linux/clk-provider.h> | ||
16 | #include <linux/mfd/syscon.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/regmap.h> | ||
22 | |||
23 | #define AP806_SAR_REG 0x400 | ||
24 | #define AP806_SAR_CLKFREQ_MODE_MASK 0x1f | ||
25 | |||
26 | #define AP806_CLK_NUM 4 | ||
27 | |||
28 | static struct clk *ap806_clks[AP806_CLK_NUM]; | ||
29 | |||
30 | static struct clk_onecell_data ap806_clk_data = { | ||
31 | .clks = ap806_clks, | ||
32 | .clk_num = AP806_CLK_NUM, | ||
33 | }; | ||
34 | |||
35 | static int ap806_syscon_clk_probe(struct platform_device *pdev) | ||
36 | { | ||
37 | unsigned int freq_mode, cpuclk_freq; | ||
38 | const char *name, *fixedclk_name; | ||
39 | struct device_node *np = pdev->dev.of_node; | ||
40 | struct regmap *regmap; | ||
41 | u32 reg; | ||
42 | int ret; | ||
43 | |||
44 | regmap = syscon_node_to_regmap(np); | ||
45 | if (IS_ERR(regmap)) { | ||
46 | dev_err(&pdev->dev, "cannot get regmap\n"); | ||
47 | return PTR_ERR(regmap); | ||
48 | } | ||
49 | |||
50 | ret = regmap_read(regmap, AP806_SAR_REG, ®); | ||
51 | if (ret) { | ||
52 | dev_err(&pdev->dev, "cannot read from regmap\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK; | ||
57 | switch (freq_mode) { | ||
58 | case 0x0 ... 0x5: | ||
59 | cpuclk_freq = 2000; | ||
60 | break; | ||
61 | case 0x6 ... 0xB: | ||
62 | cpuclk_freq = 1800; | ||
63 | break; | ||
64 | case 0xC ... 0x11: | ||
65 | cpuclk_freq = 1600; | ||
66 | break; | ||
67 | case 0x12 ... 0x16: | ||
68 | cpuclk_freq = 1400; | ||
69 | break; | ||
70 | case 0x17 ... 0x19: | ||
71 | cpuclk_freq = 1300; | ||
72 | break; | ||
73 | default: | ||
74 | dev_err(&pdev->dev, "invalid SAR value\n"); | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | |||
78 | /* Convert to hertz */ | ||
79 | cpuclk_freq *= 1000 * 1000; | ||
80 | |||
81 | /* CPU clocks depend on the Sample At Reset configuration */ | ||
82 | of_property_read_string_index(np, "clock-output-names", | ||
83 | 0, &name); | ||
84 | ap806_clks[0] = clk_register_fixed_rate(&pdev->dev, name, NULL, | ||
85 | 0, cpuclk_freq); | ||
86 | if (IS_ERR(ap806_clks[0])) { | ||
87 | ret = PTR_ERR(ap806_clks[0]); | ||
88 | goto fail0; | ||
89 | } | ||
90 | |||
91 | of_property_read_string_index(np, "clock-output-names", | ||
92 | 1, &name); | ||
93 | ap806_clks[1] = clk_register_fixed_rate(&pdev->dev, name, NULL, 0, | ||
94 | cpuclk_freq); | ||
95 | if (IS_ERR(ap806_clks[1])) { | ||
96 | ret = PTR_ERR(ap806_clks[1]); | ||
97 | goto fail1; | ||
98 | } | ||
99 | |||
100 | /* Fixed clock is always 1200 Mhz */ | ||
101 | of_property_read_string_index(np, "clock-output-names", | ||
102 | 2, &fixedclk_name); | ||
103 | ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL, | ||
104 | 0, 1200 * 1000 * 1000); | ||
105 | if (IS_ERR(ap806_clks[2])) { | ||
106 | ret = PTR_ERR(ap806_clks[2]); | ||
107 | goto fail2; | ||
108 | } | ||
109 | |||
110 | /* MSS Clock is fixed clock divided by 6 */ | ||
111 | of_property_read_string_index(np, "clock-output-names", | ||
112 | 3, &name); | ||
113 | ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name, | ||
114 | 0, 1, 6); | ||
115 | if (IS_ERR(ap806_clks[3])) { | ||
116 | ret = PTR_ERR(ap806_clks[3]); | ||
117 | goto fail3; | ||
118 | } | ||
119 | |||
120 | ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); | ||
121 | if (ret) | ||
122 | goto fail_clk_add; | ||
123 | |||
124 | return 0; | ||
125 | |||
126 | fail_clk_add: | ||
127 | clk_unregister_fixed_factor(ap806_clks[3]); | ||
128 | fail3: | ||
129 | clk_unregister_fixed_rate(ap806_clks[2]); | ||
130 | fail2: | ||
131 | clk_unregister_fixed_rate(ap806_clks[1]); | ||
132 | fail1: | ||
133 | clk_unregister_fixed_rate(ap806_clks[0]); | ||
134 | fail0: | ||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | static int ap806_syscon_clk_remove(struct platform_device *pdev) | ||
139 | { | ||
140 | of_clk_del_provider(pdev->dev.of_node); | ||
141 | clk_unregister_fixed_factor(ap806_clks[3]); | ||
142 | clk_unregister_fixed_rate(ap806_clks[2]); | ||
143 | clk_unregister_fixed_rate(ap806_clks[1]); | ||
144 | clk_unregister_fixed_rate(ap806_clks[0]); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static const struct of_device_id ap806_syscon_of_match[] = { | ||
150 | { .compatible = "marvell,ap806-system-controller", }, | ||
151 | { } | ||
152 | }; | ||
153 | MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match); | ||
154 | |||
155 | static struct platform_driver ap806_syscon_driver = { | ||
156 | .probe = ap806_syscon_clk_probe, | ||
157 | .remove = ap806_syscon_clk_remove, | ||
158 | .driver = { | ||
159 | .name = "marvell-ap806-system-controller", | ||
160 | .of_match_table = ap806_syscon_of_match, | ||
161 | }, | ||
162 | }; | ||
163 | |||
164 | module_platform_driver(ap806_syscon_driver); | ||
165 | |||
166 | MODULE_DESCRIPTION("Marvell AP806 System Controller driver"); | ||
167 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | ||
168 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c new file mode 100644 index 000000000000..7fa42d6b2b92 --- /dev/null +++ b/drivers/clk/mvebu/cp110-system-controller.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* | ||
2 | * Marvell Armada CP110 System Controller | ||
3 | * | ||
4 | * Copyright (C) 2016 Marvell | ||
5 | * | ||
6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * CP110 has 5 core clocks: | ||
15 | * | ||
16 | * - APLL (1 Ghz) | ||
17 | * - PPv2 core (1/3 APLL) | ||
18 | * - EIP (1/2 APLL) | ||
19 | * - Core (1/2 EIP) | ||
20 | * | ||
21 | * - NAND clock, which is either: | ||
22 | * - Equal to the core clock | ||
23 | * - 2/5 APLL | ||
24 | * | ||
25 | * CP110 has 32 gatable clocks, for the various peripherals in the | ||
26 | * IP. They have fairly complicated parent/child relationships. | ||
27 | */ | ||
28 | |||
29 | #define pr_fmt(fmt) "cp110-system-controller: " fmt | ||
30 | |||
31 | #include <linux/clk-provider.h> | ||
32 | #include <linux/mfd/syscon.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/of.h> | ||
35 | #include <linux/of_address.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/regmap.h> | ||
38 | #include <linux/slab.h> | ||
39 | |||
40 | #define CP110_PM_CLOCK_GATING_REG 0x220 | ||
41 | #define CP110_NAND_FLASH_CLK_CTRL_REG 0x700 | ||
42 | #define NF_CLOCK_SEL_400_MASK BIT(0) | ||
43 | |||
44 | enum { | ||
45 | CP110_CLK_TYPE_CORE, | ||
46 | CP110_CLK_TYPE_GATABLE, | ||
47 | }; | ||
48 | |||
49 | #define CP110_MAX_CORE_CLOCKS 5 | ||
50 | #define CP110_MAX_GATABLE_CLOCKS 32 | ||
51 | |||
52 | #define CP110_CLK_NUM \ | ||
53 | (CP110_MAX_CORE_CLOCKS + CP110_MAX_GATABLE_CLOCKS) | ||
54 | |||
55 | #define CP110_CORE_APLL 0 | ||
56 | #define CP110_CORE_PPV2 1 | ||
57 | #define CP110_CORE_EIP 2 | ||
58 | #define CP110_CORE_CORE 3 | ||
59 | #define CP110_CORE_NAND 4 | ||
60 | |||
61 | /* A number of gatable clocks need special handling */ | ||
62 | #define CP110_GATE_AUDIO 0 | ||
63 | #define CP110_GATE_COMM_UNIT 1 | ||
64 | #define CP110_GATE_NAND 2 | ||
65 | #define CP110_GATE_PPV2 3 | ||
66 | #define CP110_GATE_SDIO 4 | ||
67 | #define CP110_GATE_XOR1 7 | ||
68 | #define CP110_GATE_XOR0 8 | ||
69 | #define CP110_GATE_PCIE_X1_0 11 | ||
70 | #define CP110_GATE_PCIE_X1_1 12 | ||
71 | #define CP110_GATE_PCIE_X4 13 | ||
72 | #define CP110_GATE_PCIE_XOR 14 | ||
73 | #define CP110_GATE_SATA 15 | ||
74 | #define CP110_GATE_SATA_USB 16 | ||
75 | #define CP110_GATE_MAIN 17 | ||
76 | #define CP110_GATE_SDMMC 18 | ||
77 | #define CP110_GATE_SLOW_IO 21 | ||
78 | #define CP110_GATE_USB3H0 22 | ||
79 | #define CP110_GATE_USB3H1 23 | ||
80 | #define CP110_GATE_USB3DEV 24 | ||
81 | #define CP110_GATE_EIP150 25 | ||
82 | #define CP110_GATE_EIP197 26 | ||
83 | |||
84 | static struct clk *cp110_clks[CP110_CLK_NUM]; | ||
85 | |||
86 | static struct clk_onecell_data cp110_clk_data = { | ||
87 | .clks = cp110_clks, | ||
88 | .clk_num = CP110_CLK_NUM, | ||
89 | }; | ||
90 | |||
91 | struct cp110_gate_clk { | ||
92 | struct clk_hw hw; | ||
93 | struct regmap *regmap; | ||
94 | u8 bit_idx; | ||
95 | }; | ||
96 | |||
97 | #define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw) | ||
98 | |||
99 | static int cp110_gate_enable(struct clk_hw *hw) | ||
100 | { | ||
101 | struct cp110_gate_clk *gate = to_cp110_gate_clk(hw); | ||
102 | |||
103 | regmap_update_bits(gate->regmap, CP110_PM_CLOCK_GATING_REG, | ||
104 | BIT(gate->bit_idx), BIT(gate->bit_idx)); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void cp110_gate_disable(struct clk_hw *hw) | ||
110 | { | ||
111 | struct cp110_gate_clk *gate = to_cp110_gate_clk(hw); | ||
112 | |||
113 | regmap_update_bits(gate->regmap, CP110_PM_CLOCK_GATING_REG, | ||
114 | BIT(gate->bit_idx), 0); | ||
115 | } | ||
116 | |||
117 | static int cp110_gate_is_enabled(struct clk_hw *hw) | ||
118 | { | ||
119 | struct cp110_gate_clk *gate = to_cp110_gate_clk(hw); | ||
120 | u32 val; | ||
121 | |||
122 | regmap_read(gate->regmap, CP110_PM_CLOCK_GATING_REG, &val); | ||
123 | |||
124 | return val & BIT(gate->bit_idx); | ||
125 | } | ||
126 | |||
127 | static const struct clk_ops cp110_gate_ops = { | ||
128 | .enable = cp110_gate_enable, | ||
129 | .disable = cp110_gate_disable, | ||
130 | .is_enabled = cp110_gate_is_enabled, | ||
131 | }; | ||
132 | |||
133 | static struct clk *cp110_register_gate(const char *name, | ||
134 | const char *parent_name, | ||
135 | struct regmap *regmap, u8 bit_idx) | ||
136 | { | ||
137 | struct cp110_gate_clk *gate; | ||
138 | struct clk *clk; | ||
139 | struct clk_init_data init; | ||
140 | |||
141 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
142 | if (!gate) | ||
143 | return ERR_PTR(-ENOMEM); | ||
144 | |||
145 | init.name = name; | ||
146 | init.ops = &cp110_gate_ops; | ||
147 | init.parent_names = &parent_name; | ||
148 | init.num_parents = 1; | ||
149 | |||
150 | gate->regmap = regmap; | ||
151 | gate->bit_idx = bit_idx; | ||
152 | gate->hw.init = &init; | ||
153 | |||
154 | clk = clk_register(NULL, &gate->hw); | ||
155 | if (IS_ERR(clk)) | ||
156 | kfree(gate); | ||
157 | |||
158 | return clk; | ||
159 | } | ||
160 | |||
161 | static void cp110_unregister_gate(struct clk *clk) | ||
162 | { | ||
163 | struct clk_hw *hw; | ||
164 | |||
165 | hw = __clk_get_hw(clk); | ||
166 | if (!hw) | ||
167 | return; | ||
168 | |||
169 | clk_unregister(clk); | ||
170 | kfree(to_cp110_gate_clk(hw)); | ||
171 | } | ||
172 | |||
173 | static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data) | ||
174 | { | ||
175 | struct clk_onecell_data *clk_data = data; | ||
176 | unsigned int type = clkspec->args[0]; | ||
177 | unsigned int idx = clkspec->args[1]; | ||
178 | |||
179 | if (type == CP110_CLK_TYPE_CORE) { | ||
180 | if (idx > CP110_MAX_CORE_CLOCKS) | ||
181 | return ERR_PTR(-EINVAL); | ||
182 | return clk_data->clks[idx]; | ||
183 | } else if (type == CP110_CLK_TYPE_GATABLE) { | ||
184 | if (idx > CP110_MAX_GATABLE_CLOCKS) | ||
185 | return ERR_PTR(-EINVAL); | ||
186 | return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx]; | ||
187 | } | ||
188 | |||
189 | return ERR_PTR(-EINVAL); | ||
190 | } | ||
191 | |||
192 | static int cp110_syscon_clk_probe(struct platform_device *pdev) | ||
193 | { | ||
194 | struct regmap *regmap; | ||
195 | struct device_node *np = pdev->dev.of_node; | ||
196 | const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name; | ||
197 | struct clk *clk; | ||
198 | u32 nand_clk_ctrl; | ||
199 | int i, ret; | ||
200 | |||
201 | regmap = syscon_node_to_regmap(np); | ||
202 | if (IS_ERR(regmap)) | ||
203 | return PTR_ERR(regmap); | ||
204 | |||
205 | ret = regmap_read(regmap, CP110_NAND_FLASH_CLK_CTRL_REG, | ||
206 | &nand_clk_ctrl); | ||
207 | if (ret) | ||
208 | return ret; | ||
209 | |||
210 | /* Register the APLL which is the root of the clk tree */ | ||
211 | of_property_read_string_index(np, "core-clock-output-names", | ||
212 | CP110_CORE_APLL, &apll_name); | ||
213 | clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0, | ||
214 | 1000 * 1000 * 1000); | ||
215 | if (IS_ERR(clk)) { | ||
216 | ret = PTR_ERR(clk); | ||
217 | goto fail0; | ||
218 | } | ||
219 | |||
220 | cp110_clks[CP110_CORE_APLL] = clk; | ||
221 | |||
222 | /* PPv2 is APLL/3 */ | ||
223 | of_property_read_string_index(np, "core-clock-output-names", | ||
224 | CP110_CORE_PPV2, &ppv2_name); | ||
225 | clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3); | ||
226 | if (IS_ERR(clk)) { | ||
227 | ret = PTR_ERR(clk); | ||
228 | goto fail1; | ||
229 | } | ||
230 | |||
231 | cp110_clks[CP110_CORE_PPV2] = clk; | ||
232 | |||
233 | /* EIP clock is APLL/2 */ | ||
234 | of_property_read_string_index(np, "core-clock-output-names", | ||
235 | CP110_CORE_EIP, &eip_name); | ||
236 | clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2); | ||
237 | if (IS_ERR(clk)) { | ||
238 | ret = PTR_ERR(clk); | ||
239 | goto fail2; | ||
240 | } | ||
241 | |||
242 | cp110_clks[CP110_CORE_EIP] = clk; | ||
243 | |||
244 | /* Core clock is EIP/2 */ | ||
245 | of_property_read_string_index(np, "core-clock-output-names", | ||
246 | CP110_CORE_CORE, &core_name); | ||
247 | clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2); | ||
248 | if (IS_ERR(clk)) { | ||
249 | ret = PTR_ERR(clk); | ||
250 | goto fail3; | ||
251 | } | ||
252 | |||
253 | cp110_clks[CP110_CORE_CORE] = clk; | ||
254 | |||
255 | /* NAND can be either APLL/2.5 or core clock */ | ||
256 | of_property_read_string_index(np, "core-clock-output-names", | ||
257 | CP110_CORE_NAND, &nand_name); | ||
258 | if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK) | ||
259 | clk = clk_register_fixed_factor(NULL, nand_name, | ||
260 | apll_name, 0, 2, 5); | ||
261 | else | ||
262 | clk = clk_register_fixed_factor(NULL, nand_name, | ||
263 | core_name, 0, 1, 1); | ||
264 | if (IS_ERR(clk)) { | ||
265 | ret = PTR_ERR(clk); | ||
266 | goto fail4; | ||
267 | } | ||
268 | |||
269 | cp110_clks[CP110_CORE_NAND] = clk; | ||
270 | |||
271 | for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { | ||
272 | const char *parent, *name; | ||
273 | int ret; | ||
274 | |||
275 | ret = of_property_read_string_index(np, | ||
276 | "gate-clock-output-names", | ||
277 | i, &name); | ||
278 | /* Reached the end of the list? */ | ||
279 | if (ret < 0) | ||
280 | break; | ||
281 | |||
282 | if (!strcmp(name, "none")) | ||
283 | continue; | ||
284 | |||
285 | switch (i) { | ||
286 | case CP110_GATE_AUDIO: | ||
287 | case CP110_GATE_COMM_UNIT: | ||
288 | case CP110_GATE_EIP150: | ||
289 | case CP110_GATE_EIP197: | ||
290 | case CP110_GATE_SLOW_IO: | ||
291 | of_property_read_string_index(np, | ||
292 | "gate-clock-output-names", | ||
293 | CP110_GATE_MAIN, &parent); | ||
294 | break; | ||
295 | case CP110_GATE_NAND: | ||
296 | parent = nand_name; | ||
297 | break; | ||
298 | case CP110_GATE_PPV2: | ||
299 | parent = ppv2_name; | ||
300 | break; | ||
301 | case CP110_GATE_SDIO: | ||
302 | of_property_read_string_index(np, | ||
303 | "gate-clock-output-names", | ||
304 | CP110_GATE_SDMMC, &parent); | ||
305 | break; | ||
306 | case CP110_GATE_XOR1: | ||
307 | case CP110_GATE_XOR0: | ||
308 | case CP110_GATE_PCIE_X1_0: | ||
309 | case CP110_GATE_PCIE_X1_1: | ||
310 | case CP110_GATE_PCIE_X4: | ||
311 | of_property_read_string_index(np, | ||
312 | "gate-clock-output-names", | ||
313 | CP110_GATE_PCIE_XOR, &parent); | ||
314 | break; | ||
315 | case CP110_GATE_SATA: | ||
316 | case CP110_GATE_USB3H0: | ||
317 | case CP110_GATE_USB3H1: | ||
318 | case CP110_GATE_USB3DEV: | ||
319 | of_property_read_string_index(np, | ||
320 | "gate-clock-output-names", | ||
321 | CP110_GATE_SATA_USB, &parent); | ||
322 | break; | ||
323 | default: | ||
324 | parent = core_name; | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | clk = cp110_register_gate(name, parent, regmap, i); | ||
329 | if (IS_ERR(clk)) { | ||
330 | ret = PTR_ERR(clk); | ||
331 | goto fail_gate; | ||
332 | } | ||
333 | |||
334 | cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk; | ||
335 | } | ||
336 | |||
337 | ret = of_clk_add_provider(np, cp110_of_clk_get, &cp110_clk_data); | ||
338 | if (ret) | ||
339 | goto fail_clk_add; | ||
340 | |||
341 | return 0; | ||
342 | |||
343 | fail_clk_add: | ||
344 | fail_gate: | ||
345 | for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { | ||
346 | clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; | ||
347 | |||
348 | if (clk) | ||
349 | cp110_unregister_gate(clk); | ||
350 | } | ||
351 | |||
352 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); | ||
353 | fail4: | ||
354 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); | ||
355 | fail3: | ||
356 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); | ||
357 | fail2: | ||
358 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); | ||
359 | fail1: | ||
360 | clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); | ||
361 | fail0: | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static int cp110_syscon_clk_remove(struct platform_device *pdev) | ||
366 | { | ||
367 | int i; | ||
368 | |||
369 | of_clk_del_provider(pdev->dev.of_node); | ||
370 | |||
371 | for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) { | ||
372 | struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i]; | ||
373 | |||
374 | if (clk) | ||
375 | cp110_unregister_gate(clk); | ||
376 | } | ||
377 | |||
378 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); | ||
379 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); | ||
380 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]); | ||
381 | clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]); | ||
382 | clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]); | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static const struct of_device_id cp110_syscon_of_match[] = { | ||
388 | { .compatible = "marvell,cp110-system-controller0", }, | ||
389 | { } | ||
390 | }; | ||
391 | MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match); | ||
392 | |||
393 | static struct platform_driver cp110_syscon_driver = { | ||
394 | .probe = cp110_syscon_clk_probe, | ||
395 | .remove = cp110_syscon_clk_remove, | ||
396 | .driver = { | ||
397 | .name = "marvell-cp110-system-controller0", | ||
398 | .of_match_table = cp110_syscon_of_match, | ||
399 | }, | ||
400 | }; | ||
401 | |||
402 | module_platform_driver(cp110_syscon_driver); | ||
403 | |||
404 | MODULE_DESCRIPTION("Marvell CP110 System Controller 0 driver"); | ||
405 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | ||
406 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/clk/nxp/clk-lpc18xx-creg.c b/drivers/clk/nxp/clk-lpc18xx-creg.c index d44b61afa2dc..9e35749dafdf 100644 --- a/drivers/clk/nxp/clk-lpc18xx-creg.c +++ b/drivers/clk/nxp/clk-lpc18xx-creg.c | |||
@@ -147,6 +147,7 @@ static struct clk *clk_register_creg_clk(struct device *dev, | |||
147 | init.name = creg_clk->name; | 147 | init.name = creg_clk->name; |
148 | init.parent_names = parent_name; | 148 | init.parent_names = parent_name; |
149 | init.num_parents = 1; | 149 | init.num_parents = 1; |
150 | init.flags = 0; | ||
150 | 151 | ||
151 | creg_clk->reg = syscon; | 152 | creg_clk->reg = syscon; |
152 | creg_clk->hw.init = &init; | 153 | creg_clk->hw.init = &init; |
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index 9c29080a84d8..5c4e193164d4 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c | |||
@@ -2346,6 +2346,7 @@ static struct clk_branch gcc_crypto_ahb_clk = { | |||
2346 | "pcnoc_bfdcd_clk_src", | 2346 | "pcnoc_bfdcd_clk_src", |
2347 | }, | 2347 | }, |
2348 | .num_parents = 1, | 2348 | .num_parents = 1, |
2349 | .flags = CLK_SET_RATE_PARENT, | ||
2349 | .ops = &clk_branch2_ops, | 2350 | .ops = &clk_branch2_ops, |
2350 | }, | 2351 | }, |
2351 | }, | 2352 | }, |
@@ -2381,6 +2382,7 @@ static struct clk_branch gcc_crypto_clk = { | |||
2381 | "crypto_clk_src", | 2382 | "crypto_clk_src", |
2382 | }, | 2383 | }, |
2383 | .num_parents = 1, | 2384 | .num_parents = 1, |
2385 | .flags = CLK_SET_RATE_PARENT, | ||
2384 | .ops = &clk_branch2_ops, | 2386 | .ops = &clk_branch2_ops, |
2385 | }, | 2387 | }, |
2386 | }, | 2388 | }, |
diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c index 6df7ff36b416..847dd9dadeca 100644 --- a/drivers/clk/qcom/mmcc-msm8996.c +++ b/drivers/clk/qcom/mmcc-msm8996.c | |||
@@ -1279,21 +1279,6 @@ static struct clk_branch mmss_misc_cxo_clk = { | |||
1279 | }, | 1279 | }, |
1280 | }; | 1280 | }; |
1281 | 1281 | ||
1282 | static struct clk_branch mmss_mmagic_axi_clk = { | ||
1283 | .halt_reg = 0x506c, | ||
1284 | .clkr = { | ||
1285 | .enable_reg = 0x506c, | ||
1286 | .enable_mask = BIT(0), | ||
1287 | .hw.init = &(struct clk_init_data){ | ||
1288 | .name = "mmss_mmagic_axi_clk", | ||
1289 | .parent_names = (const char *[]){ "axi_clk_src" }, | ||
1290 | .num_parents = 1, | ||
1291 | .flags = CLK_SET_RATE_PARENT, | ||
1292 | .ops = &clk_branch2_ops, | ||
1293 | }, | ||
1294 | }, | ||
1295 | }; | ||
1296 | |||
1297 | static struct clk_branch mmss_mmagic_maxi_clk = { | 1282 | static struct clk_branch mmss_mmagic_maxi_clk = { |
1298 | .halt_reg = 0x5074, | 1283 | .halt_reg = 0x5074, |
1299 | .clkr = { | 1284 | .clkr = { |
@@ -1579,21 +1564,6 @@ static struct clk_branch smmu_video_axi_clk = { | |||
1579 | }, | 1564 | }, |
1580 | }; | 1565 | }; |
1581 | 1566 | ||
1582 | static struct clk_branch mmagic_bimc_axi_clk = { | ||
1583 | .halt_reg = 0x5294, | ||
1584 | .clkr = { | ||
1585 | .enable_reg = 0x5294, | ||
1586 | .enable_mask = BIT(0), | ||
1587 | .hw.init = &(struct clk_init_data){ | ||
1588 | .name = "mmagic_bimc_axi_clk", | ||
1589 | .parent_names = (const char *[]){ "axi_clk_src" }, | ||
1590 | .num_parents = 1, | ||
1591 | .flags = CLK_SET_RATE_PARENT, | ||
1592 | .ops = &clk_branch2_ops, | ||
1593 | }, | ||
1594 | }, | ||
1595 | }; | ||
1596 | |||
1597 | static struct clk_branch mmagic_bimc_noc_cfg_ahb_clk = { | 1567 | static struct clk_branch mmagic_bimc_noc_cfg_ahb_clk = { |
1598 | .halt_reg = 0x5298, | 1568 | .halt_reg = 0x5298, |
1599 | .clkr = { | 1569 | .clkr = { |
@@ -3121,7 +3091,6 @@ static struct clk_regmap *mmcc_msm8996_clocks[] = { | |||
3121 | [MMSS_MMAGIC_CFG_AHB_CLK] = &mmss_mmagic_cfg_ahb_clk.clkr, | 3091 | [MMSS_MMAGIC_CFG_AHB_CLK] = &mmss_mmagic_cfg_ahb_clk.clkr, |
3122 | [MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr, | 3092 | [MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr, |
3123 | [MMSS_MISC_CXO_CLK] = &mmss_misc_cxo_clk.clkr, | 3093 | [MMSS_MISC_CXO_CLK] = &mmss_misc_cxo_clk.clkr, |
3124 | [MMSS_MMAGIC_AXI_CLK] = &mmss_mmagic_axi_clk.clkr, | ||
3125 | [MMSS_MMAGIC_MAXI_CLK] = &mmss_mmagic_maxi_clk.clkr, | 3094 | [MMSS_MMAGIC_MAXI_CLK] = &mmss_mmagic_maxi_clk.clkr, |
3126 | [MMAGIC_CAMSS_AXI_CLK] = &mmagic_camss_axi_clk.clkr, | 3095 | [MMAGIC_CAMSS_AXI_CLK] = &mmagic_camss_axi_clk.clkr, |
3127 | [MMAGIC_CAMSS_NOC_CFG_AHB_CLK] = &mmagic_camss_noc_cfg_ahb_clk.clkr, | 3096 | [MMAGIC_CAMSS_NOC_CFG_AHB_CLK] = &mmagic_camss_noc_cfg_ahb_clk.clkr, |
@@ -3141,7 +3110,6 @@ static struct clk_regmap *mmcc_msm8996_clocks[] = { | |||
3141 | [MMAGIC_VIDEO_NOC_CFG_AHB_CLK] = &mmagic_video_noc_cfg_ahb_clk.clkr, | 3110 | [MMAGIC_VIDEO_NOC_CFG_AHB_CLK] = &mmagic_video_noc_cfg_ahb_clk.clkr, |
3142 | [SMMU_VIDEO_AHB_CLK] = &smmu_video_ahb_clk.clkr, | 3111 | [SMMU_VIDEO_AHB_CLK] = &smmu_video_ahb_clk.clkr, |
3143 | [SMMU_VIDEO_AXI_CLK] = &smmu_video_axi_clk.clkr, | 3112 | [SMMU_VIDEO_AXI_CLK] = &smmu_video_axi_clk.clkr, |
3144 | [MMAGIC_BIMC_AXI_CLK] = &mmagic_bimc_axi_clk.clkr, | ||
3145 | [MMAGIC_BIMC_NOC_CFG_AHB_CLK] = &mmagic_bimc_noc_cfg_ahb_clk.clkr, | 3113 | [MMAGIC_BIMC_NOC_CFG_AHB_CLK] = &mmagic_bimc_noc_cfg_ahb_clk.clkr, |
3146 | [GPU_GX_GFX3D_CLK] = &gpu_gx_gfx3d_clk.clkr, | 3114 | [GPU_GX_GFX3D_CLK] = &gpu_gx_gfx3d_clk.clkr, |
3147 | [GPU_GX_RBBMTIMER_CLK] = &gpu_gx_rbbmtimer_clk.clkr, | 3115 | [GPU_GX_RBBMTIMER_CLK] = &gpu_gx_rbbmtimer_clk.clkr, |
diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c index 8b597b9a3804..5093a250650d 100644 --- a/drivers/clk/renesas/clk-mstp.c +++ b/drivers/clk/renesas/clk-mstp.c | |||
@@ -316,11 +316,10 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) | |||
316 | return; | 316 | return; |
317 | 317 | ||
318 | pd->name = np->name; | 318 | pd->name = np->name; |
319 | |||
320 | pd->flags = GENPD_FLAG_PM_CLK; | 319 | pd->flags = GENPD_FLAG_PM_CLK; |
321 | pm_genpd_init(pd, &simple_qos_governor, false); | ||
322 | pd->attach_dev = cpg_mstp_attach_dev; | 320 | pd->attach_dev = cpg_mstp_attach_dev; |
323 | pd->detach_dev = cpg_mstp_detach_dev; | 321 | pd->detach_dev = cpg_mstp_detach_dev; |
322 | pm_genpd_init(pd, &pm_domain_always_on_gov, false); | ||
324 | 323 | ||
325 | of_genpd_add_provider_simple(np, pd); | 324 | of_genpd_add_provider_simple(np, pd); |
326 | } | 325 | } |
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 6af7f5b6e824..ca5519c583d4 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c | |||
@@ -120,6 +120,7 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { | |||
120 | DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), | 120 | DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), |
121 | DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), | 121 | DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), |
122 | DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), | 122 | DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), |
123 | DEF_DIV6P1("csi0", R8A7795_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), | ||
123 | 124 | ||
124 | DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), | 125 | DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), |
125 | DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), | 126 | DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), |
@@ -190,6 +191,10 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { | |||
190 | DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4), | 191 | DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4), |
191 | DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4), | 192 | DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4), |
192 | DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4), | 193 | DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4), |
194 | DEF_MOD("csi21", 713, R8A7795_CLK_CSI0), | ||
195 | DEF_MOD("csi20", 714, R8A7795_CLK_CSI0), | ||
196 | DEF_MOD("csi41", 715, R8A7795_CLK_CSI0), | ||
197 | DEF_MOD("csi40", 716, R8A7795_CLK_CSI0), | ||
193 | DEF_MOD("du3", 721, R8A7795_CLK_S2D1), | 198 | DEF_MOD("du3", 721, R8A7795_CLK_S2D1), |
194 | DEF_MOD("du2", 722, R8A7795_CLK_S2D1), | 199 | DEF_MOD("du2", 722, R8A7795_CLK_S2D1), |
195 | DEF_MOD("du1", 723, R8A7795_CLK_S2D1), | 200 | DEF_MOD("du1", 723, R8A7795_CLK_S2D1), |
@@ -197,6 +202,14 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { | |||
197 | DEF_MOD("lvds", 727, R8A7795_CLK_S2D1), | 202 | DEF_MOD("lvds", 727, R8A7795_CLK_S2D1), |
198 | DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), | 203 | DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), |
199 | DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), | 204 | DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), |
205 | DEF_MOD("vin7", 804, R8A7795_CLK_S2D1), | ||
206 | DEF_MOD("vin6", 805, R8A7795_CLK_S2D1), | ||
207 | DEF_MOD("vin5", 806, R8A7795_CLK_S2D1), | ||
208 | DEF_MOD("vin4", 807, R8A7795_CLK_S2D1), | ||
209 | DEF_MOD("vin3", 808, R8A7795_CLK_S2D1), | ||
210 | DEF_MOD("vin2", 809, R8A7795_CLK_S2D1), | ||
211 | DEF_MOD("vin1", 810, R8A7795_CLK_S2D1), | ||
212 | DEF_MOD("vin0", 811, R8A7795_CLK_S2D1), | ||
200 | DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2), | 213 | DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2), |
201 | DEF_MOD("sata0", 815, R8A7795_CLK_S3D2), | 214 | DEF_MOD("sata0", 815, R8A7795_CLK_S3D2), |
202 | DEF_MOD("gpio7", 905, R8A7795_CLK_CP), | 215 | DEF_MOD("gpio7", 905, R8A7795_CLK_CP), |
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1f2dc3629f0e..210cd744a7a9 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c | |||
@@ -493,9 +493,9 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, | |||
493 | genpd = &pd->genpd; | 493 | genpd = &pd->genpd; |
494 | genpd->name = np->name; | 494 | genpd->name = np->name; |
495 | genpd->flags = GENPD_FLAG_PM_CLK; | 495 | genpd->flags = GENPD_FLAG_PM_CLK; |
496 | pm_genpd_init(genpd, &simple_qos_governor, false); | ||
497 | genpd->attach_dev = cpg_mssr_attach_dev; | 496 | genpd->attach_dev = cpg_mssr_attach_dev; |
498 | genpd->detach_dev = cpg_mssr_detach_dev; | 497 | genpd->detach_dev = cpg_mssr_detach_dev; |
498 | pm_genpd_init(genpd, &pm_domain_always_on_gov, false); | ||
499 | cpg_mssr_clk_domain = pd; | 499 | cpg_mssr_clk_domain = pd; |
500 | 500 | ||
501 | of_genpd_add_provider_simple(np, genpd); | 501 | of_genpd_add_provider_simple(np, genpd); |
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 80b9a379beb4..f47a2fa962d2 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile | |||
@@ -15,3 +15,4 @@ obj-y += clk-rk3188.o | |||
15 | obj-y += clk-rk3228.o | 15 | obj-y += clk-rk3228.o |
16 | obj-y += clk-rk3288.o | 16 | obj-y += clk-rk3288.o |
17 | obj-y += clk-rk3368.o | 17 | obj-y += clk-rk3368.o |
18 | obj-y += clk-rk3399.o | ||
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 4e73ed5cab58..4bb130cd0062 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c | |||
@@ -158,12 +158,16 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, | |||
158 | 158 | ||
159 | writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask, | 159 | writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask, |
160 | reg_data->div_core_shift) | | 160 | reg_data->div_core_shift) | |
161 | HIWORD_UPDATE(1, 1, reg_data->mux_core_shift), | 161 | HIWORD_UPDATE(reg_data->mux_core_alt, |
162 | reg_data->mux_core_mask, | ||
163 | reg_data->mux_core_shift), | ||
162 | cpuclk->reg_base + reg_data->core_reg); | 164 | cpuclk->reg_base + reg_data->core_reg); |
163 | } else { | 165 | } else { |
164 | /* select alternate parent */ | 166 | /* select alternate parent */ |
165 | writel(HIWORD_UPDATE(1, 1, reg_data->mux_core_shift), | 167 | writel(HIWORD_UPDATE(reg_data->mux_core_alt, |
166 | cpuclk->reg_base + reg_data->core_reg); | 168 | reg_data->mux_core_mask, |
169 | reg_data->mux_core_shift), | ||
170 | cpuclk->reg_base + reg_data->core_reg); | ||
167 | } | 171 | } |
168 | 172 | ||
169 | spin_unlock_irqrestore(cpuclk->lock, flags); | 173 | spin_unlock_irqrestore(cpuclk->lock, flags); |
@@ -198,7 +202,9 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, | |||
198 | 202 | ||
199 | writel(HIWORD_UPDATE(0, reg_data->div_core_mask, | 203 | writel(HIWORD_UPDATE(0, reg_data->div_core_mask, |
200 | reg_data->div_core_shift) | | 204 | reg_data->div_core_shift) | |
201 | HIWORD_UPDATE(0, 1, reg_data->mux_core_shift), | 205 | HIWORD_UPDATE(reg_data->mux_core_main, |
206 | reg_data->mux_core_mask, | ||
207 | reg_data->mux_core_shift), | ||
202 | cpuclk->reg_base + reg_data->core_reg); | 208 | cpuclk->reg_base + reg_data->core_reg); |
203 | 209 | ||
204 | if (ndata->old_rate > ndata->new_rate) | 210 | if (ndata->old_rate > ndata->new_rate) |
@@ -252,7 +258,7 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, | |||
252 | return ERR_PTR(-ENOMEM); | 258 | return ERR_PTR(-ENOMEM); |
253 | 259 | ||
254 | init.name = name; | 260 | init.name = name; |
255 | init.parent_names = &parent_names[0]; | 261 | init.parent_names = &parent_names[reg_data->mux_core_main]; |
256 | init.num_parents = 1; | 262 | init.num_parents = 1; |
257 | init.ops = &rockchip_cpuclk_ops; | 263 | init.ops = &rockchip_cpuclk_ops; |
258 | 264 | ||
@@ -270,10 +276,10 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, | |||
270 | cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb; | 276 | cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb; |
271 | cpuclk->hw.init = &init; | 277 | cpuclk->hw.init = &init; |
272 | 278 | ||
273 | cpuclk->alt_parent = __clk_lookup(parent_names[1]); | 279 | cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]); |
274 | if (!cpuclk->alt_parent) { | 280 | if (!cpuclk->alt_parent) { |
275 | pr_err("%s: could not lookup alternate parent\n", | 281 | pr_err("%s: could not lookup alternate parent: (%d)\n", |
276 | __func__); | 282 | __func__, reg_data->mux_core_alt); |
277 | ret = -EINVAL; | 283 | ret = -EINVAL; |
278 | goto free_cpuclk; | 284 | goto free_cpuclk; |
279 | } | 285 | } |
@@ -285,10 +291,11 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, | |||
285 | goto free_cpuclk; | 291 | goto free_cpuclk; |
286 | } | 292 | } |
287 | 293 | ||
288 | clk = __clk_lookup(parent_names[0]); | 294 | clk = __clk_lookup(parent_names[reg_data->mux_core_main]); |
289 | if (!clk) { | 295 | if (!clk) { |
290 | pr_err("%s: could not lookup parent clock %s\n", | 296 | pr_err("%s: could not lookup parent clock: (%d) %s\n", |
291 | __func__, parent_names[0]); | 297 | __func__, reg_data->mux_core_main, |
298 | parent_names[reg_data->mux_core_main]); | ||
292 | ret = -EINVAL; | 299 | ret = -EINVAL; |
293 | goto free_alt_parent; | 300 | goto free_alt_parent; |
294 | } | 301 | } |
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c index e0dc7e83403a..bc856f21f6b2 100644 --- a/drivers/clk/rockchip/clk-mmc-phase.c +++ b/drivers/clk/rockchip/clk-mmc-phase.c | |||
@@ -123,7 +123,8 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees) | |||
123 | raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; | 123 | raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; |
124 | raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; | 124 | raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; |
125 | raw_value |= nineties; | 125 | raw_value |= nineties; |
126 | writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg); | 126 | writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), |
127 | mmc_clock->reg); | ||
127 | 128 | ||
128 | pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n", | 129 | pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n", |
129 | clk_hw_get_name(hw), degrees, delay_num, | 130 | clk_hw_get_name(hw), degrees, delay_num, |
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 5de797e34d54..db81e454166b 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c | |||
@@ -46,6 +46,8 @@ struct rockchip_clk_pll { | |||
46 | const struct rockchip_pll_rate_table *rate_table; | 46 | const struct rockchip_pll_rate_table *rate_table; |
47 | unsigned int rate_count; | 47 | unsigned int rate_count; |
48 | spinlock_t *lock; | 48 | spinlock_t *lock; |
49 | |||
50 | struct rockchip_clk_provider *ctx; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) | 53 | #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) |
@@ -90,15 +92,10 @@ static long rockchip_pll_round_rate(struct clk_hw *hw, | |||
90 | */ | 92 | */ |
91 | static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) | 93 | static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) |
92 | { | 94 | { |
93 | struct regmap *grf = rockchip_clk_get_grf(); | 95 | struct regmap *grf = pll->ctx->grf; |
94 | unsigned int val; | 96 | unsigned int val; |
95 | int delay = 24000000, ret; | 97 | int delay = 24000000, ret; |
96 | 98 | ||
97 | if (IS_ERR(grf)) { | ||
98 | pr_err("%s: grf regmap not available\n", __func__); | ||
99 | return PTR_ERR(grf); | ||
100 | } | ||
101 | |||
102 | while (delay > 0) { | 99 | while (delay > 0) { |
103 | ret = regmap_read(grf, pll->lock_offset, &val); | 100 | ret = regmap_read(grf, pll->lock_offset, &val); |
104 | if (ret) { | 101 | if (ret) { |
@@ -234,7 +231,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, | |||
234 | /* wait for the pll to lock */ | 231 | /* wait for the pll to lock */ |
235 | ret = rockchip_pll_wait_lock(pll); | 232 | ret = rockchip_pll_wait_lock(pll); |
236 | if (ret) { | 233 | if (ret) { |
237 | pr_warn("%s: pll update unsucessful, trying to restore old params\n", | 234 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n", |
238 | __func__); | 235 | __func__); |
239 | rockchip_rk3036_pll_set_params(pll, &cur); | 236 | rockchip_rk3036_pll_set_params(pll, &cur); |
240 | } | 237 | } |
@@ -250,17 +247,9 @@ static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
250 | { | 247 | { |
251 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | 248 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
252 | const struct rockchip_pll_rate_table *rate; | 249 | const struct rockchip_pll_rate_table *rate; |
253 | unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate); | ||
254 | struct regmap *grf = rockchip_clk_get_grf(); | ||
255 | 250 | ||
256 | if (IS_ERR(grf)) { | 251 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", |
257 | pr_debug("%s: grf regmap not available, aborting rate change\n", | 252 | __func__, __clk_get_name(hw->clk), drate, prate); |
258 | __func__); | ||
259 | return PTR_ERR(grf); | ||
260 | } | ||
261 | |||
262 | pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", | ||
263 | __func__, __clk_get_name(hw->clk), old_rate, drate, prate); | ||
264 | 253 | ||
265 | /* Get required rate settings from table */ | 254 | /* Get required rate settings from table */ |
266 | rate = rockchip_get_pll_settings(pll, drate); | 255 | rate = rockchip_get_pll_settings(pll, drate); |
@@ -473,7 +462,7 @@ static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll, | |||
473 | /* wait for the pll to lock */ | 462 | /* wait for the pll to lock */ |
474 | ret = rockchip_pll_wait_lock(pll); | 463 | ret = rockchip_pll_wait_lock(pll); |
475 | if (ret) { | 464 | if (ret) { |
476 | pr_warn("%s: pll update unsucessful, trying to restore old params\n", | 465 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n", |
477 | __func__); | 466 | __func__); |
478 | rockchip_rk3066_pll_set_params(pll, &cur); | 467 | rockchip_rk3066_pll_set_params(pll, &cur); |
479 | } | 468 | } |
@@ -489,17 +478,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
489 | { | 478 | { |
490 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | 479 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
491 | const struct rockchip_pll_rate_table *rate; | 480 | const struct rockchip_pll_rate_table *rate; |
492 | unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); | ||
493 | struct regmap *grf = rockchip_clk_get_grf(); | ||
494 | 481 | ||
495 | if (IS_ERR(grf)) { | 482 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", |
496 | pr_debug("%s: grf regmap not available, aborting rate change\n", | 483 | __func__, clk_hw_get_name(hw), drate, prate); |
497 | __func__); | ||
498 | return PTR_ERR(grf); | ||
499 | } | ||
500 | |||
501 | pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", | ||
502 | __func__, clk_hw_get_name(hw), old_rate, drate, prate); | ||
503 | 484 | ||
504 | /* Get required rate settings from table */ | 485 | /* Get required rate settings from table */ |
505 | rate = rockchip_get_pll_settings(pll, drate); | 486 | rate = rockchip_get_pll_settings(pll, drate); |
@@ -563,11 +544,6 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) | |||
563 | rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); | 544 | rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); |
564 | if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf | 545 | if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf |
565 | || rate->nb != cur.nb) { | 546 | || rate->nb != cur.nb) { |
566 | struct regmap *grf = rockchip_clk_get_grf(); | ||
567 | |||
568 | if (IS_ERR(grf)) | ||
569 | return; | ||
570 | |||
571 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", | 547 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", |
572 | __func__, clk_hw_get_name(hw)); | 548 | __func__, clk_hw_get_name(hw)); |
573 | rockchip_rk3066_pll_set_params(pll, rate); | 549 | rockchip_rk3066_pll_set_params(pll, rate); |
@@ -591,16 +567,277 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { | |||
591 | .init = rockchip_rk3066_pll_init, | 567 | .init = rockchip_rk3066_pll_init, |
592 | }; | 568 | }; |
593 | 569 | ||
570 | /** | ||
571 | * PLL used in RK3399 | ||
572 | */ | ||
573 | |||
574 | #define RK3399_PLLCON(i) (i * 0x4) | ||
575 | #define RK3399_PLLCON0_FBDIV_MASK 0xfff | ||
576 | #define RK3399_PLLCON0_FBDIV_SHIFT 0 | ||
577 | #define RK3399_PLLCON1_REFDIV_MASK 0x3f | ||
578 | #define RK3399_PLLCON1_REFDIV_SHIFT 0 | ||
579 | #define RK3399_PLLCON1_POSTDIV1_MASK 0x7 | ||
580 | #define RK3399_PLLCON1_POSTDIV1_SHIFT 8 | ||
581 | #define RK3399_PLLCON1_POSTDIV2_MASK 0x7 | ||
582 | #define RK3399_PLLCON1_POSTDIV2_SHIFT 12 | ||
583 | #define RK3399_PLLCON2_FRAC_MASK 0xffffff | ||
584 | #define RK3399_PLLCON2_FRAC_SHIFT 0 | ||
585 | #define RK3399_PLLCON2_LOCK_STATUS BIT(31) | ||
586 | #define RK3399_PLLCON3_PWRDOWN BIT(0) | ||
587 | #define RK3399_PLLCON3_DSMPD_MASK 0x1 | ||
588 | #define RK3399_PLLCON3_DSMPD_SHIFT 3 | ||
589 | |||
590 | static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) | ||
591 | { | ||
592 | u32 pllcon; | ||
593 | int delay = 24000000; | ||
594 | |||
595 | /* poll check the lock status in rk3399 xPLLCON2 */ | ||
596 | while (delay > 0) { | ||
597 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); | ||
598 | if (pllcon & RK3399_PLLCON2_LOCK_STATUS) | ||
599 | return 0; | ||
600 | |||
601 | delay--; | ||
602 | } | ||
603 | |||
604 | pr_err("%s: timeout waiting for pll to lock\n", __func__); | ||
605 | return -ETIMEDOUT; | ||
606 | } | ||
607 | |||
608 | static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, | ||
609 | struct rockchip_pll_rate_table *rate) | ||
610 | { | ||
611 | u32 pllcon; | ||
612 | |||
613 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0)); | ||
614 | rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT) | ||
615 | & RK3399_PLLCON0_FBDIV_MASK); | ||
616 | |||
617 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1)); | ||
618 | rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT) | ||
619 | & RK3399_PLLCON1_REFDIV_MASK); | ||
620 | rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT) | ||
621 | & RK3399_PLLCON1_POSTDIV1_MASK); | ||
622 | rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT) | ||
623 | & RK3399_PLLCON1_POSTDIV2_MASK); | ||
624 | |||
625 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); | ||
626 | rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT) | ||
627 | & RK3399_PLLCON2_FRAC_MASK); | ||
628 | |||
629 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3)); | ||
630 | rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT) | ||
631 | & RK3399_PLLCON3_DSMPD_MASK); | ||
632 | } | ||
633 | |||
634 | static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw, | ||
635 | unsigned long prate) | ||
636 | { | ||
637 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
638 | struct rockchip_pll_rate_table cur; | ||
639 | u64 rate64 = prate; | ||
640 | |||
641 | rockchip_rk3399_pll_get_params(pll, &cur); | ||
642 | |||
643 | rate64 *= cur.fbdiv; | ||
644 | do_div(rate64, cur.refdiv); | ||
645 | |||
646 | if (cur.dsmpd == 0) { | ||
647 | /* fractional mode */ | ||
648 | u64 frac_rate64 = prate * cur.frac; | ||
649 | |||
650 | do_div(frac_rate64, cur.refdiv); | ||
651 | rate64 += frac_rate64 >> 24; | ||
652 | } | ||
653 | |||
654 | do_div(rate64, cur.postdiv1); | ||
655 | do_div(rate64, cur.postdiv2); | ||
656 | |||
657 | return (unsigned long)rate64; | ||
658 | } | ||
659 | |||
660 | static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, | ||
661 | const struct rockchip_pll_rate_table *rate) | ||
662 | { | ||
663 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; | ||
664 | struct clk_mux *pll_mux = &pll->pll_mux; | ||
665 | struct rockchip_pll_rate_table cur; | ||
666 | u32 pllcon; | ||
667 | int rate_change_remuxed = 0; | ||
668 | int cur_parent; | ||
669 | int ret; | ||
670 | |||
671 | pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", | ||
672 | __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, | ||
673 | rate->postdiv2, rate->dsmpd, rate->frac); | ||
674 | |||
675 | rockchip_rk3399_pll_get_params(pll, &cur); | ||
676 | cur.rate = 0; | ||
677 | |||
678 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); | ||
679 | if (cur_parent == PLL_MODE_NORM) { | ||
680 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); | ||
681 | rate_change_remuxed = 1; | ||
682 | } | ||
683 | |||
684 | /* update pll values */ | ||
685 | writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK, | ||
686 | RK3399_PLLCON0_FBDIV_SHIFT), | ||
687 | pll->reg_base + RK3399_PLLCON(0)); | ||
688 | |||
689 | writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK, | ||
690 | RK3399_PLLCON1_REFDIV_SHIFT) | | ||
691 | HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK, | ||
692 | RK3399_PLLCON1_POSTDIV1_SHIFT) | | ||
693 | HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK, | ||
694 | RK3399_PLLCON1_POSTDIV2_SHIFT), | ||
695 | pll->reg_base + RK3399_PLLCON(1)); | ||
696 | |||
697 | /* xPLL CON2 is not HIWORD_MASK */ | ||
698 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); | ||
699 | pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT); | ||
700 | pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT; | ||
701 | writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2)); | ||
702 | |||
703 | writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK, | ||
704 | RK3399_PLLCON3_DSMPD_SHIFT), | ||
705 | pll->reg_base + RK3399_PLLCON(3)); | ||
706 | |||
707 | /* wait for the pll to lock */ | ||
708 | ret = rockchip_rk3399_pll_wait_lock(pll); | ||
709 | if (ret) { | ||
710 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n", | ||
711 | __func__); | ||
712 | rockchip_rk3399_pll_set_params(pll, &cur); | ||
713 | } | ||
714 | |||
715 | if (rate_change_remuxed) | ||
716 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); | ||
717 | |||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate, | ||
722 | unsigned long prate) | ||
723 | { | ||
724 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
725 | const struct rockchip_pll_rate_table *rate; | ||
726 | |||
727 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", | ||
728 | __func__, __clk_get_name(hw->clk), drate, prate); | ||
729 | |||
730 | /* Get required rate settings from table */ | ||
731 | rate = rockchip_get_pll_settings(pll, drate); | ||
732 | if (!rate) { | ||
733 | pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, | ||
734 | drate, __clk_get_name(hw->clk)); | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | |||
738 | return rockchip_rk3399_pll_set_params(pll, rate); | ||
739 | } | ||
740 | |||
741 | static int rockchip_rk3399_pll_enable(struct clk_hw *hw) | ||
742 | { | ||
743 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
744 | |||
745 | writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), | ||
746 | pll->reg_base + RK3399_PLLCON(3)); | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static void rockchip_rk3399_pll_disable(struct clk_hw *hw) | ||
752 | { | ||
753 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
754 | |||
755 | writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, | ||
756 | RK3399_PLLCON3_PWRDOWN, 0), | ||
757 | pll->reg_base + RK3399_PLLCON(3)); | ||
758 | } | ||
759 | |||
760 | static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw) | ||
761 | { | ||
762 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
763 | u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3)); | ||
764 | |||
765 | return !(pllcon & RK3399_PLLCON3_PWRDOWN); | ||
766 | } | ||
767 | |||
768 | static void rockchip_rk3399_pll_init(struct clk_hw *hw) | ||
769 | { | ||
770 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
771 | const struct rockchip_pll_rate_table *rate; | ||
772 | struct rockchip_pll_rate_table cur; | ||
773 | unsigned long drate; | ||
774 | |||
775 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) | ||
776 | return; | ||
777 | |||
778 | drate = clk_hw_get_rate(hw); | ||
779 | rate = rockchip_get_pll_settings(pll, drate); | ||
780 | |||
781 | /* when no rate setting for the current rate, rely on clk_set_rate */ | ||
782 | if (!rate) | ||
783 | return; | ||
784 | |||
785 | rockchip_rk3399_pll_get_params(pll, &cur); | ||
786 | |||
787 | pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk), | ||
788 | drate); | ||
789 | pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", | ||
790 | cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, | ||
791 | cur.dsmpd, cur.frac); | ||
792 | pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", | ||
793 | rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, | ||
794 | rate->dsmpd, rate->frac); | ||
795 | |||
796 | if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || | ||
797 | rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || | ||
798 | rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) { | ||
799 | struct clk *parent = clk_get_parent(hw->clk); | ||
800 | |||
801 | if (!parent) { | ||
802 | pr_warn("%s: parent of %s not available\n", | ||
803 | __func__, __clk_get_name(hw->clk)); | ||
804 | return; | ||
805 | } | ||
806 | |||
807 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", | ||
808 | __func__, __clk_get_name(hw->clk)); | ||
809 | rockchip_rk3399_pll_set_params(pll, rate); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = { | ||
814 | .recalc_rate = rockchip_rk3399_pll_recalc_rate, | ||
815 | .enable = rockchip_rk3399_pll_enable, | ||
816 | .disable = rockchip_rk3399_pll_disable, | ||
817 | .is_enabled = rockchip_rk3399_pll_is_enabled, | ||
818 | }; | ||
819 | |||
820 | static const struct clk_ops rockchip_rk3399_pll_clk_ops = { | ||
821 | .recalc_rate = rockchip_rk3399_pll_recalc_rate, | ||
822 | .round_rate = rockchip_pll_round_rate, | ||
823 | .set_rate = rockchip_rk3399_pll_set_rate, | ||
824 | .enable = rockchip_rk3399_pll_enable, | ||
825 | .disable = rockchip_rk3399_pll_disable, | ||
826 | .is_enabled = rockchip_rk3399_pll_is_enabled, | ||
827 | .init = rockchip_rk3399_pll_init, | ||
828 | }; | ||
829 | |||
594 | /* | 830 | /* |
595 | * Common registering of pll clocks | 831 | * Common registering of pll clocks |
596 | */ | 832 | */ |
597 | 833 | ||
598 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | 834 | struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, |
835 | enum rockchip_pll_type pll_type, | ||
599 | const char *name, const char *const *parent_names, | 836 | const char *name, const char *const *parent_names, |
600 | u8 num_parents, void __iomem *base, int con_offset, | 837 | u8 num_parents, int con_offset, int grf_lock_offset, |
601 | int grf_lock_offset, int lock_shift, int mode_offset, | 838 | int lock_shift, int mode_offset, int mode_shift, |
602 | int mode_shift, struct rockchip_pll_rate_table *rate_table, | 839 | struct rockchip_pll_rate_table *rate_table, |
603 | u8 clk_pll_flags, spinlock_t *lock) | 840 | u8 clk_pll_flags) |
604 | { | 841 | { |
605 | const char *pll_parents[3]; | 842 | const char *pll_parents[3]; |
606 | struct clk_init_data init; | 843 | struct clk_init_data init; |
@@ -624,14 +861,16 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
624 | /* create the mux on top of the real pll */ | 861 | /* create the mux on top of the real pll */ |
625 | pll->pll_mux_ops = &clk_mux_ops; | 862 | pll->pll_mux_ops = &clk_mux_ops; |
626 | pll_mux = &pll->pll_mux; | 863 | pll_mux = &pll->pll_mux; |
627 | pll_mux->reg = base + mode_offset; | 864 | pll_mux->reg = ctx->reg_base + mode_offset; |
628 | pll_mux->shift = mode_shift; | 865 | pll_mux->shift = mode_shift; |
629 | pll_mux->mask = PLL_MODE_MASK; | 866 | pll_mux->mask = PLL_MODE_MASK; |
630 | pll_mux->flags = 0; | 867 | pll_mux->flags = 0; |
631 | pll_mux->lock = lock; | 868 | pll_mux->lock = &ctx->lock; |
632 | pll_mux->hw.init = &init; | 869 | pll_mux->hw.init = &init; |
633 | 870 | ||
634 | if (pll_type == pll_rk3036 || pll_type == pll_rk3066) | 871 | if (pll_type == pll_rk3036 || |
872 | pll_type == pll_rk3066 || | ||
873 | pll_type == pll_rk3399) | ||
635 | pll_mux->flags |= CLK_MUX_HIWORD_MASK; | 874 | pll_mux->flags |= CLK_MUX_HIWORD_MASK; |
636 | 875 | ||
637 | /* the actual muxing is xin24m, pll-output, xin32k */ | 876 | /* the actual muxing is xin24m, pll-output, xin32k */ |
@@ -677,17 +916,23 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
677 | 916 | ||
678 | switch (pll_type) { | 917 | switch (pll_type) { |
679 | case pll_rk3036: | 918 | case pll_rk3036: |
680 | if (!pll->rate_table) | 919 | if (!pll->rate_table || IS_ERR(ctx->grf)) |
681 | init.ops = &rockchip_rk3036_pll_clk_norate_ops; | 920 | init.ops = &rockchip_rk3036_pll_clk_norate_ops; |
682 | else | 921 | else |
683 | init.ops = &rockchip_rk3036_pll_clk_ops; | 922 | init.ops = &rockchip_rk3036_pll_clk_ops; |
684 | break; | 923 | break; |
685 | case pll_rk3066: | 924 | case pll_rk3066: |
686 | if (!pll->rate_table) | 925 | if (!pll->rate_table || IS_ERR(ctx->grf)) |
687 | init.ops = &rockchip_rk3066_pll_clk_norate_ops; | 926 | init.ops = &rockchip_rk3066_pll_clk_norate_ops; |
688 | else | 927 | else |
689 | init.ops = &rockchip_rk3066_pll_clk_ops; | 928 | init.ops = &rockchip_rk3066_pll_clk_ops; |
690 | break; | 929 | break; |
930 | case pll_rk3399: | ||
931 | if (!pll->rate_table) | ||
932 | init.ops = &rockchip_rk3399_pll_clk_norate_ops; | ||
933 | else | ||
934 | init.ops = &rockchip_rk3399_pll_clk_ops; | ||
935 | break; | ||
691 | default: | 936 | default: |
692 | pr_warn("%s: Unknown pll type for pll clk %s\n", | 937 | pr_warn("%s: Unknown pll type for pll clk %s\n", |
693 | __func__, name); | 938 | __func__, name); |
@@ -695,11 +940,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
695 | 940 | ||
696 | pll->hw.init = &init; | 941 | pll->hw.init = &init; |
697 | pll->type = pll_type; | 942 | pll->type = pll_type; |
698 | pll->reg_base = base + con_offset; | 943 | pll->reg_base = ctx->reg_base + con_offset; |
699 | pll->lock_offset = grf_lock_offset; | 944 | pll->lock_offset = grf_lock_offset; |
700 | pll->lock_shift = lock_shift; | 945 | pll->lock_shift = lock_shift; |
701 | pll->flags = clk_pll_flags; | 946 | pll->flags = clk_pll_flags; |
702 | pll->lock = lock; | 947 | pll->lock = &ctx->lock; |
948 | pll->ctx = ctx; | ||
703 | 949 | ||
704 | pll_clk = clk_register(NULL, &pll->hw); | 950 | pll_clk = clk_register(NULL, &pll->hw); |
705 | if (IS_ERR(pll_clk)) { | 951 | if (IS_ERR(pll_clk)) { |
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 7cdb2d61f3e0..924f560dcf80 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c | |||
@@ -113,7 +113,10 @@ static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { | |||
113 | .core_reg = RK2928_CLKSEL_CON(0), | 113 | .core_reg = RK2928_CLKSEL_CON(0), |
114 | .div_core_shift = 0, | 114 | .div_core_shift = 0, |
115 | .div_core_mask = 0x1f, | 115 | .div_core_mask = 0x1f, |
116 | .mux_core_alt = 1, | ||
117 | .mux_core_main = 0, | ||
116 | .mux_core_shift = 7, | 118 | .mux_core_shift = 7, |
119 | .mux_core_mask = 0x1, | ||
117 | }; | 120 | }; |
118 | 121 | ||
119 | PNAME(mux_pll_p) = { "xin24m", "xin24m" }; | 122 | PNAME(mux_pll_p) = { "xin24m", "xin24m" }; |
@@ -437,6 +440,7 @@ static const char *const rk3036_critical_clocks[] __initconst = { | |||
437 | 440 | ||
438 | static void __init rk3036_clk_init(struct device_node *np) | 441 | static void __init rk3036_clk_init(struct device_node *np) |
439 | { | 442 | { |
443 | struct rockchip_clk_provider *ctx; | ||
440 | void __iomem *reg_base; | 444 | void __iomem *reg_base; |
441 | struct clk *clk; | 445 | struct clk *clk; |
442 | 446 | ||
@@ -446,22 +450,27 @@ static void __init rk3036_clk_init(struct device_node *np) | |||
446 | return; | 450 | return; |
447 | } | 451 | } |
448 | 452 | ||
449 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 453 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
454 | if (IS_ERR(ctx)) { | ||
455 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
456 | iounmap(reg_base); | ||
457 | return; | ||
458 | } | ||
450 | 459 | ||
451 | clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); | 460 | clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); |
452 | if (IS_ERR(clk)) | 461 | if (IS_ERR(clk)) |
453 | pr_warn("%s: could not register clock usb480m: %ld\n", | 462 | pr_warn("%s: could not register clock usb480m: %ld\n", |
454 | __func__, PTR_ERR(clk)); | 463 | __func__, PTR_ERR(clk)); |
455 | 464 | ||
456 | rockchip_clk_register_plls(rk3036_pll_clks, | 465 | rockchip_clk_register_plls(ctx, rk3036_pll_clks, |
457 | ARRAY_SIZE(rk3036_pll_clks), | 466 | ARRAY_SIZE(rk3036_pll_clks), |
458 | RK3036_GRF_SOC_STATUS0); | 467 | RK3036_GRF_SOC_STATUS0); |
459 | rockchip_clk_register_branches(rk3036_clk_branches, | 468 | rockchip_clk_register_branches(ctx, rk3036_clk_branches, |
460 | ARRAY_SIZE(rk3036_clk_branches)); | 469 | ARRAY_SIZE(rk3036_clk_branches)); |
461 | rockchip_clk_protect_critical(rk3036_critical_clocks, | 470 | rockchip_clk_protect_critical(rk3036_critical_clocks, |
462 | ARRAY_SIZE(rk3036_critical_clocks)); | 471 | ARRAY_SIZE(rk3036_critical_clocks)); |
463 | 472 | ||
464 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 473 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
465 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 474 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
466 | &rk3036_cpuclk_data, rk3036_cpuclk_rates, | 475 | &rk3036_cpuclk_data, rk3036_cpuclk_rates, |
467 | ARRAY_SIZE(rk3036_cpuclk_rates)); | 476 | ARRAY_SIZE(rk3036_cpuclk_rates)); |
@@ -469,6 +478,8 @@ static void __init rk3036_clk_init(struct device_node *np) | |||
469 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | 478 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), |
470 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 479 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
471 | 480 | ||
472 | rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); | 481 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); |
482 | |||
483 | rockchip_clk_of_add_provider(np, ctx); | ||
473 | } | 484 | } |
474 | CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init); | 485 | CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 40bab3901491..d0e722a0e8cf 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c | |||
@@ -155,7 +155,10 @@ static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = { | |||
155 | .core_reg = RK2928_CLKSEL_CON(0), | 155 | .core_reg = RK2928_CLKSEL_CON(0), |
156 | .div_core_shift = 0, | 156 | .div_core_shift = 0, |
157 | .div_core_mask = 0x1f, | 157 | .div_core_mask = 0x1f, |
158 | .mux_core_alt = 1, | ||
159 | .mux_core_main = 0, | ||
158 | .mux_core_shift = 8, | 160 | .mux_core_shift = 8, |
161 | .mux_core_mask = 0x1, | ||
159 | }; | 162 | }; |
160 | 163 | ||
161 | #define RK3188_DIV_ACLK_CORE_MASK 0x7 | 164 | #define RK3188_DIV_ACLK_CORE_MASK 0x7 |
@@ -191,7 +194,10 @@ static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = { | |||
191 | .core_reg = RK2928_CLKSEL_CON(0), | 194 | .core_reg = RK2928_CLKSEL_CON(0), |
192 | .div_core_shift = 9, | 195 | .div_core_shift = 9, |
193 | .div_core_mask = 0x1f, | 196 | .div_core_mask = 0x1f, |
197 | .mux_core_alt = 1, | ||
198 | .mux_core_main = 0, | ||
194 | .mux_core_shift = 8, | 199 | .mux_core_shift = 8, |
200 | .mux_core_mask = 0x1, | ||
195 | }; | 201 | }; |
196 | 202 | ||
197 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; | 203 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; |
@@ -753,57 +759,75 @@ static const char *const rk3188_critical_clocks[] __initconst = { | |||
753 | "hclk_cpubus" | 759 | "hclk_cpubus" |
754 | }; | 760 | }; |
755 | 761 | ||
756 | static void __init rk3188_common_clk_init(struct device_node *np) | 762 | static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) |
757 | { | 763 | { |
764 | struct rockchip_clk_provider *ctx; | ||
758 | void __iomem *reg_base; | 765 | void __iomem *reg_base; |
759 | 766 | ||
760 | reg_base = of_iomap(np, 0); | 767 | reg_base = of_iomap(np, 0); |
761 | if (!reg_base) { | 768 | if (!reg_base) { |
762 | pr_err("%s: could not map cru region\n", __func__); | 769 | pr_err("%s: could not map cru region\n", __func__); |
763 | return; | 770 | return ERR_PTR(-ENOMEM); |
764 | } | 771 | } |
765 | 772 | ||
766 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 773 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
774 | if (IS_ERR(ctx)) { | ||
775 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
776 | iounmap(reg_base); | ||
777 | return ERR_PTR(-ENOMEM); | ||
778 | } | ||
767 | 779 | ||
768 | rockchip_clk_register_branches(common_clk_branches, | 780 | rockchip_clk_register_branches(ctx, common_clk_branches, |
769 | ARRAY_SIZE(common_clk_branches)); | 781 | ARRAY_SIZE(common_clk_branches)); |
770 | 782 | ||
771 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | 783 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), |
772 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 784 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
773 | 785 | ||
774 | rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); | 786 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); |
787 | |||
788 | return ctx; | ||
775 | } | 789 | } |
776 | 790 | ||
777 | static void __init rk3066a_clk_init(struct device_node *np) | 791 | static void __init rk3066a_clk_init(struct device_node *np) |
778 | { | 792 | { |
779 | rk3188_common_clk_init(np); | 793 | struct rockchip_clk_provider *ctx; |
780 | rockchip_clk_register_plls(rk3066_pll_clks, | 794 | |
795 | ctx = rk3188_common_clk_init(np); | ||
796 | if (IS_ERR(ctx)) | ||
797 | return; | ||
798 | |||
799 | rockchip_clk_register_plls(ctx, rk3066_pll_clks, | ||
781 | ARRAY_SIZE(rk3066_pll_clks), | 800 | ARRAY_SIZE(rk3066_pll_clks), |
782 | RK3066_GRF_SOC_STATUS); | 801 | RK3066_GRF_SOC_STATUS); |
783 | rockchip_clk_register_branches(rk3066a_clk_branches, | 802 | rockchip_clk_register_branches(ctx, rk3066a_clk_branches, |
784 | ARRAY_SIZE(rk3066a_clk_branches)); | 803 | ARRAY_SIZE(rk3066a_clk_branches)); |
785 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 804 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
786 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 805 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
787 | &rk3066_cpuclk_data, rk3066_cpuclk_rates, | 806 | &rk3066_cpuclk_data, rk3066_cpuclk_rates, |
788 | ARRAY_SIZE(rk3066_cpuclk_rates)); | 807 | ARRAY_SIZE(rk3066_cpuclk_rates)); |
789 | rockchip_clk_protect_critical(rk3188_critical_clocks, | 808 | rockchip_clk_protect_critical(rk3188_critical_clocks, |
790 | ARRAY_SIZE(rk3188_critical_clocks)); | 809 | ARRAY_SIZE(rk3188_critical_clocks)); |
810 | rockchip_clk_of_add_provider(np, ctx); | ||
791 | } | 811 | } |
792 | CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); | 812 | CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); |
793 | 813 | ||
794 | static void __init rk3188a_clk_init(struct device_node *np) | 814 | static void __init rk3188a_clk_init(struct device_node *np) |
795 | { | 815 | { |
816 | struct rockchip_clk_provider *ctx; | ||
796 | struct clk *clk1, *clk2; | 817 | struct clk *clk1, *clk2; |
797 | unsigned long rate; | 818 | unsigned long rate; |
798 | int ret; | 819 | int ret; |
799 | 820 | ||
800 | rk3188_common_clk_init(np); | 821 | ctx = rk3188_common_clk_init(np); |
801 | rockchip_clk_register_plls(rk3188_pll_clks, | 822 | if (IS_ERR(ctx)) |
823 | return; | ||
824 | |||
825 | rockchip_clk_register_plls(ctx, rk3188_pll_clks, | ||
802 | ARRAY_SIZE(rk3188_pll_clks), | 826 | ARRAY_SIZE(rk3188_pll_clks), |
803 | RK3188_GRF_SOC_STATUS); | 827 | RK3188_GRF_SOC_STATUS); |
804 | rockchip_clk_register_branches(rk3188_clk_branches, | 828 | rockchip_clk_register_branches(ctx, rk3188_clk_branches, |
805 | ARRAY_SIZE(rk3188_clk_branches)); | 829 | ARRAY_SIZE(rk3188_clk_branches)); |
806 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 830 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
807 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 831 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
808 | &rk3188_cpuclk_data, rk3188_cpuclk_rates, | 832 | &rk3188_cpuclk_data, rk3188_cpuclk_rates, |
809 | ARRAY_SIZE(rk3188_cpuclk_rates)); | 833 | ARRAY_SIZE(rk3188_cpuclk_rates)); |
@@ -827,6 +851,7 @@ static void __init rk3188a_clk_init(struct device_node *np) | |||
827 | 851 | ||
828 | rockchip_clk_protect_critical(rk3188_critical_clocks, | 852 | rockchip_clk_protect_critical(rk3188_critical_clocks, |
829 | ARRAY_SIZE(rk3188_critical_clocks)); | 853 | ARRAY_SIZE(rk3188_critical_clocks)); |
854 | rockchip_clk_of_add_provider(np, ctx); | ||
830 | } | 855 | } |
831 | CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); | 856 | CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); |
832 | 857 | ||
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 7702d2855e9c..016bdb0b793a 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c | |||
@@ -111,7 +111,10 @@ static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { | |||
111 | .core_reg = RK2928_CLKSEL_CON(0), | 111 | .core_reg = RK2928_CLKSEL_CON(0), |
112 | .div_core_shift = 0, | 112 | .div_core_shift = 0, |
113 | .div_core_mask = 0x1f, | 113 | .div_core_mask = 0x1f, |
114 | .mux_core_alt = 1, | ||
115 | .mux_core_main = 0, | ||
114 | .mux_core_shift = 6, | 116 | .mux_core_shift = 6, |
117 | .mux_core_mask = 0x1, | ||
115 | }; | 118 | }; |
116 | 119 | ||
117 | PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; | 120 | PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; |
@@ -625,6 +628,7 @@ static const char *const rk3228_critical_clocks[] __initconst = { | |||
625 | 628 | ||
626 | static void __init rk3228_clk_init(struct device_node *np) | 629 | static void __init rk3228_clk_init(struct device_node *np) |
627 | { | 630 | { |
631 | struct rockchip_clk_provider *ctx; | ||
628 | void __iomem *reg_base; | 632 | void __iomem *reg_base; |
629 | 633 | ||
630 | reg_base = of_iomap(np, 0); | 634 | reg_base = of_iomap(np, 0); |
@@ -633,17 +637,22 @@ static void __init rk3228_clk_init(struct device_node *np) | |||
633 | return; | 637 | return; |
634 | } | 638 | } |
635 | 639 | ||
636 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 640 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
641 | if (IS_ERR(ctx)) { | ||
642 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
643 | iounmap(reg_base); | ||
644 | return; | ||
645 | } | ||
637 | 646 | ||
638 | rockchip_clk_register_plls(rk3228_pll_clks, | 647 | rockchip_clk_register_plls(ctx, rk3228_pll_clks, |
639 | ARRAY_SIZE(rk3228_pll_clks), | 648 | ARRAY_SIZE(rk3228_pll_clks), |
640 | RK3228_GRF_SOC_STATUS0); | 649 | RK3228_GRF_SOC_STATUS0); |
641 | rockchip_clk_register_branches(rk3228_clk_branches, | 650 | rockchip_clk_register_branches(ctx, rk3228_clk_branches, |
642 | ARRAY_SIZE(rk3228_clk_branches)); | 651 | ARRAY_SIZE(rk3228_clk_branches)); |
643 | rockchip_clk_protect_critical(rk3228_critical_clocks, | 652 | rockchip_clk_protect_critical(rk3228_critical_clocks, |
644 | ARRAY_SIZE(rk3228_critical_clocks)); | 653 | ARRAY_SIZE(rk3228_critical_clocks)); |
645 | 654 | ||
646 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 655 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
647 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 656 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
648 | &rk3228_cpuclk_data, rk3228_cpuclk_rates, | 657 | &rk3228_cpuclk_data, rk3228_cpuclk_rates, |
649 | ARRAY_SIZE(rk3228_cpuclk_rates)); | 658 | ARRAY_SIZE(rk3228_cpuclk_rates)); |
@@ -651,6 +660,8 @@ static void __init rk3228_clk_init(struct device_node *np) | |||
651 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | 660 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), |
652 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 661 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
653 | 662 | ||
654 | rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL); | 663 | rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, NULL); |
664 | |||
665 | rockchip_clk_of_add_provider(np, ctx); | ||
655 | } | 666 | } |
656 | CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init); | 667 | CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 3cb72163a512..39af05a589b3 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c | |||
@@ -165,7 +165,10 @@ static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = { | |||
165 | .core_reg = RK3288_CLKSEL_CON(0), | 165 | .core_reg = RK3288_CLKSEL_CON(0), |
166 | .div_core_shift = 8, | 166 | .div_core_shift = 8, |
167 | .div_core_mask = 0x1f, | 167 | .div_core_mask = 0x1f, |
168 | .mux_core_alt = 1, | ||
169 | .mux_core_main = 0, | ||
168 | .mux_core_shift = 15, | 170 | .mux_core_shift = 15, |
171 | .mux_core_mask = 0x1, | ||
169 | }; | 172 | }; |
170 | 173 | ||
171 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; | 174 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; |
@@ -878,6 +881,7 @@ static struct syscore_ops rk3288_clk_syscore_ops = { | |||
878 | 881 | ||
879 | static void __init rk3288_clk_init(struct device_node *np) | 882 | static void __init rk3288_clk_init(struct device_node *np) |
880 | { | 883 | { |
884 | struct rockchip_clk_provider *ctx; | ||
881 | struct clk *clk; | 885 | struct clk *clk; |
882 | 886 | ||
883 | rk3288_cru_base = of_iomap(np, 0); | 887 | rk3288_cru_base = of_iomap(np, 0); |
@@ -886,7 +890,12 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
886 | return; | 890 | return; |
887 | } | 891 | } |
888 | 892 | ||
889 | rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); | 893 | ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); |
894 | if (IS_ERR(ctx)) { | ||
895 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
896 | iounmap(rk3288_cru_base); | ||
897 | return; | ||
898 | } | ||
890 | 899 | ||
891 | /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ | 900 | /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ |
892 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); | 901 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); |
@@ -894,17 +903,17 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
894 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", | 903 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", |
895 | __func__, PTR_ERR(clk)); | 904 | __func__, PTR_ERR(clk)); |
896 | else | 905 | else |
897 | rockchip_clk_add_lookup(clk, PCLK_WDT); | 906 | rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); |
898 | 907 | ||
899 | rockchip_clk_register_plls(rk3288_pll_clks, | 908 | rockchip_clk_register_plls(ctx, rk3288_pll_clks, |
900 | ARRAY_SIZE(rk3288_pll_clks), | 909 | ARRAY_SIZE(rk3288_pll_clks), |
901 | RK3288_GRF_SOC_STATUS1); | 910 | RK3288_GRF_SOC_STATUS1); |
902 | rockchip_clk_register_branches(rk3288_clk_branches, | 911 | rockchip_clk_register_branches(ctx, rk3288_clk_branches, |
903 | ARRAY_SIZE(rk3288_clk_branches)); | 912 | ARRAY_SIZE(rk3288_clk_branches)); |
904 | rockchip_clk_protect_critical(rk3288_critical_clocks, | 913 | rockchip_clk_protect_critical(rk3288_critical_clocks, |
905 | ARRAY_SIZE(rk3288_critical_clocks)); | 914 | ARRAY_SIZE(rk3288_critical_clocks)); |
906 | 915 | ||
907 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 916 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
908 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 917 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
909 | &rk3288_cpuclk_data, rk3288_cpuclk_rates, | 918 | &rk3288_cpuclk_data, rk3288_cpuclk_rates, |
910 | ARRAY_SIZE(rk3288_cpuclk_rates)); | 919 | ARRAY_SIZE(rk3288_cpuclk_rates)); |
@@ -913,8 +922,10 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
913 | rk3288_cru_base + RK3288_SOFTRST_CON(0), | 922 | rk3288_cru_base + RK3288_SOFTRST_CON(0), |
914 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 923 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
915 | 924 | ||
916 | rockchip_register_restart_notifier(RK3288_GLB_SRST_FST, | 925 | rockchip_register_restart_notifier(ctx, RK3288_GLB_SRST_FST, |
917 | rk3288_clk_shutdown); | 926 | rk3288_clk_shutdown); |
918 | register_syscore_ops(&rk3288_clk_syscore_ops); | 927 | register_syscore_ops(&rk3288_clk_syscore_ops); |
928 | |||
929 | rockchip_clk_of_add_provider(np, ctx); | ||
919 | } | 930 | } |
920 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); | 931 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index a2bb12200465..6cb474c593e7 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c | |||
@@ -165,14 +165,20 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = { | |||
165 | .core_reg = RK3368_CLKSEL_CON(0), | 165 | .core_reg = RK3368_CLKSEL_CON(0), |
166 | .div_core_shift = 0, | 166 | .div_core_shift = 0, |
167 | .div_core_mask = 0x1f, | 167 | .div_core_mask = 0x1f, |
168 | .mux_core_alt = 1, | ||
169 | .mux_core_main = 0, | ||
168 | .mux_core_shift = 7, | 170 | .mux_core_shift = 7, |
171 | .mux_core_mask = 0x1, | ||
169 | }; | 172 | }; |
170 | 173 | ||
171 | static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { | 174 | static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { |
172 | .core_reg = RK3368_CLKSEL_CON(2), | 175 | .core_reg = RK3368_CLKSEL_CON(2), |
173 | .div_core_shift = 0, | 176 | .div_core_shift = 0, |
177 | .mux_core_alt = 1, | ||
178 | .mux_core_main = 0, | ||
174 | .div_core_mask = 0x1f, | 179 | .div_core_mask = 0x1f, |
175 | .mux_core_shift = 7, | 180 | .mux_core_shift = 7, |
181 | .mux_core_mask = 0x1, | ||
176 | }; | 182 | }; |
177 | 183 | ||
178 | #define RK3368_DIV_ACLKM_MASK 0x1f | 184 | #define RK3368_DIV_ACLKM_MASK 0x1f |
@@ -856,6 +862,7 @@ static const char *const rk3368_critical_clocks[] __initconst = { | |||
856 | 862 | ||
857 | static void __init rk3368_clk_init(struct device_node *np) | 863 | static void __init rk3368_clk_init(struct device_node *np) |
858 | { | 864 | { |
865 | struct rockchip_clk_provider *ctx; | ||
859 | void __iomem *reg_base; | 866 | void __iomem *reg_base; |
860 | struct clk *clk; | 867 | struct clk *clk; |
861 | 868 | ||
@@ -865,7 +872,12 @@ static void __init rk3368_clk_init(struct device_node *np) | |||
865 | return; | 872 | return; |
866 | } | 873 | } |
867 | 874 | ||
868 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 875 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
876 | if (IS_ERR(ctx)) { | ||
877 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
878 | iounmap(reg_base); | ||
879 | return; | ||
880 | } | ||
869 | 881 | ||
870 | /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */ | 882 | /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */ |
871 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); | 883 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); |
@@ -873,22 +885,22 @@ static void __init rk3368_clk_init(struct device_node *np) | |||
873 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", | 885 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", |
874 | __func__, PTR_ERR(clk)); | 886 | __func__, PTR_ERR(clk)); |
875 | else | 887 | else |
876 | rockchip_clk_add_lookup(clk, PCLK_WDT); | 888 | rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); |
877 | 889 | ||
878 | rockchip_clk_register_plls(rk3368_pll_clks, | 890 | rockchip_clk_register_plls(ctx, rk3368_pll_clks, |
879 | ARRAY_SIZE(rk3368_pll_clks), | 891 | ARRAY_SIZE(rk3368_pll_clks), |
880 | RK3368_GRF_SOC_STATUS0); | 892 | RK3368_GRF_SOC_STATUS0); |
881 | rockchip_clk_register_branches(rk3368_clk_branches, | 893 | rockchip_clk_register_branches(ctx, rk3368_clk_branches, |
882 | ARRAY_SIZE(rk3368_clk_branches)); | 894 | ARRAY_SIZE(rk3368_clk_branches)); |
883 | rockchip_clk_protect_critical(rk3368_critical_clocks, | 895 | rockchip_clk_protect_critical(rk3368_critical_clocks, |
884 | ARRAY_SIZE(rk3368_critical_clocks)); | 896 | ARRAY_SIZE(rk3368_critical_clocks)); |
885 | 897 | ||
886 | rockchip_clk_register_armclk(ARMCLKB, "armclkb", | 898 | rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb", |
887 | mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), | 899 | mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), |
888 | &rk3368_cpuclkb_data, rk3368_cpuclkb_rates, | 900 | &rk3368_cpuclkb_data, rk3368_cpuclkb_rates, |
889 | ARRAY_SIZE(rk3368_cpuclkb_rates)); | 901 | ARRAY_SIZE(rk3368_cpuclkb_rates)); |
890 | 902 | ||
891 | rockchip_clk_register_armclk(ARMCLKL, "armclkl", | 903 | rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl", |
892 | mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), | 904 | mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), |
893 | &rk3368_cpuclkl_data, rk3368_cpuclkl_rates, | 905 | &rk3368_cpuclkl_data, rk3368_cpuclkl_rates, |
894 | ARRAY_SIZE(rk3368_cpuclkl_rates)); | 906 | ARRAY_SIZE(rk3368_cpuclkl_rates)); |
@@ -896,6 +908,8 @@ static void __init rk3368_clk_init(struct device_node *np) | |||
896 | rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0), | 908 | rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0), |
897 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 909 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
898 | 910 | ||
899 | rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL); | 911 | rockchip_register_restart_notifier(ctx, RK3368_GLB_SRST_FST, NULL); |
912 | |||
913 | rockchip_clk_of_add_provider(np, ctx); | ||
900 | } | 914 | } |
901 | CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init); | 915 | CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c new file mode 100644 index 000000000000..291543f52caa --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3399.c | |||
@@ -0,0 +1,1573 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Rockchip Electronics Co. Ltd. | ||
3 | * Author: Xing Zheng <zhengxing@rock-chips.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/regmap.h> | ||
21 | #include <dt-bindings/clock/rk3399-cru.h> | ||
22 | #include "clk.h" | ||
23 | |||
24 | enum rk3399_plls { | ||
25 | lpll, bpll, dpll, cpll, gpll, npll, vpll, | ||
26 | }; | ||
27 | |||
28 | enum rk3399_pmu_plls { | ||
29 | ppll, | ||
30 | }; | ||
31 | |||
32 | static struct rockchip_pll_rate_table rk3399_pll_rates[] = { | ||
33 | /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ | ||
34 | RK3036_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0), | ||
35 | RK3036_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0), | ||
36 | RK3036_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0), | ||
37 | RK3036_PLL_RATE(2136000000, 1, 89, 1, 1, 1, 0), | ||
38 | RK3036_PLL_RATE(2112000000, 1, 88, 1, 1, 1, 0), | ||
39 | RK3036_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0), | ||
40 | RK3036_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0), | ||
41 | RK3036_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0), | ||
42 | RK3036_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0), | ||
43 | RK3036_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0), | ||
44 | RK3036_PLL_RATE(1968000000, 1, 82, 1, 1, 1, 0), | ||
45 | RK3036_PLL_RATE(1944000000, 1, 81, 1, 1, 1, 0), | ||
46 | RK3036_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0), | ||
47 | RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), | ||
48 | RK3036_PLL_RATE(1872000000, 1, 78, 1, 1, 1, 0), | ||
49 | RK3036_PLL_RATE(1848000000, 1, 77, 1, 1, 1, 0), | ||
50 | RK3036_PLL_RATE(1824000000, 1, 76, 1, 1, 1, 0), | ||
51 | RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), | ||
52 | RK3036_PLL_RATE(1776000000, 1, 74, 1, 1, 1, 0), | ||
53 | RK3036_PLL_RATE(1752000000, 1, 73, 1, 1, 1, 0), | ||
54 | RK3036_PLL_RATE(1728000000, 1, 72, 1, 1, 1, 0), | ||
55 | RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), | ||
56 | RK3036_PLL_RATE(1680000000, 1, 70, 1, 1, 1, 0), | ||
57 | RK3036_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0), | ||
58 | RK3036_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0), | ||
59 | RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), | ||
60 | RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), | ||
61 | RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), | ||
62 | RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), | ||
63 | RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), | ||
64 | RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), | ||
65 | RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), | ||
66 | RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), | ||
67 | RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), | ||
68 | RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), | ||
69 | RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), | ||
70 | RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), | ||
71 | RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), | ||
72 | RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), | ||
73 | RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), | ||
74 | RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), | ||
75 | RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), | ||
76 | RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), | ||
77 | RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), | ||
78 | RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), | ||
79 | RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), | ||
80 | RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), | ||
81 | RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), | ||
82 | RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), | ||
83 | RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), | ||
84 | RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), | ||
85 | RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), | ||
86 | RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), | ||
87 | RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), | ||
88 | RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), | ||
89 | RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), | ||
90 | RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), | ||
91 | RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), | ||
92 | RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), | ||
93 | RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), | ||
94 | RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), | ||
95 | RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0), | ||
96 | RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), | ||
97 | RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), | ||
98 | RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), | ||
99 | RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), | ||
100 | RK3036_PLL_RATE( 297000000, 1, 99, 4, 2, 1, 0), | ||
101 | RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), | ||
102 | RK3036_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0), | ||
103 | RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), | ||
104 | RK3036_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0), | ||
105 | RK3036_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0), | ||
106 | RK3036_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0), | ||
107 | { /* sentinel */ }, | ||
108 | }; | ||
109 | |||
110 | /* CRU parents */ | ||
111 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; | ||
112 | |||
113 | PNAME(mux_armclkl_p) = { "clk_core_l_lpll_src", | ||
114 | "clk_core_l_bpll_src", | ||
115 | "clk_core_l_dpll_src", | ||
116 | "clk_core_l_gpll_src" }; | ||
117 | PNAME(mux_armclkb_p) = { "clk_core_b_lpll_src", | ||
118 | "clk_core_b_bpll_src", | ||
119 | "clk_core_b_dpll_src", | ||
120 | "clk_core_b_gpll_src" }; | ||
121 | PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src", | ||
122 | "gpll_aclk_cci_src", | ||
123 | "npll_aclk_cci_src", | ||
124 | "vpll_aclk_cci_src" }; | ||
125 | PNAME(mux_cci_trace_p) = { "cpll_cci_trace", | ||
126 | "gpll_cci_trace" }; | ||
127 | PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs", | ||
128 | "npll_cs"}; | ||
129 | PNAME(mux_aclk_perihp_p) = { "cpll_aclk_perihp_src", | ||
130 | "gpll_aclk_perihp_src" }; | ||
131 | |||
132 | PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; | ||
133 | PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; | ||
134 | PNAME(mux_pll_src_cpll_gpll_ppll_p) = { "cpll", "gpll", "ppll" }; | ||
135 | PNAME(mux_pll_src_cpll_gpll_upll_p) = { "cpll", "gpll", "upll" }; | ||
136 | PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; | ||
137 | PNAME(mux_pll_src_cpll_gpll_npll_ppll_p) = { "cpll", "gpll", "npll", | ||
138 | "ppll" }; | ||
139 | PNAME(mux_pll_src_cpll_gpll_npll_24m_p) = { "cpll", "gpll", "npll", | ||
140 | "xin24m" }; | ||
141 | PNAME(mux_pll_src_cpll_gpll_npll_usbphy480m_p) = { "cpll", "gpll", "npll", | ||
142 | "clk_usbphy_480m" }; | ||
143 | PNAME(mux_pll_src_ppll_cpll_gpll_npll_p) = { "ppll", "cpll", "gpll", | ||
144 | "npll", "upll" }; | ||
145 | PNAME(mux_pll_src_cpll_gpll_npll_upll_24m_p) = { "cpll", "gpll", "npll", | ||
146 | "upll", "xin24m" }; | ||
147 | PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll", | ||
148 | "ppll", "upll", "xin24m" }; | ||
149 | |||
150 | PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" }; | ||
151 | PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll", | ||
152 | "npll" }; | ||
153 | PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll", | ||
154 | "xin24m" }; | ||
155 | |||
156 | PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div", | ||
157 | "dclk_vop0_frac" }; | ||
158 | PNAME(mux_dclk_vop1_p) = { "dclk_vop1_div", | ||
159 | "dclk_vop1_frac" }; | ||
160 | |||
161 | PNAME(mux_clk_cif_p) = { "clk_cifout_src", "xin24m" }; | ||
162 | |||
163 | PNAME(mux_pll_src_24m_usbphy480m_p) = { "xin24m", "clk_usbphy_480m" }; | ||
164 | PNAME(mux_pll_src_24m_pciephy_p) = { "xin24m", "clk_pciephy_ref100m" }; | ||
165 | PNAME(mux_pll_src_24m_32k_cpll_gpll_p) = { "xin24m", "xin32k", | ||
166 | "cpll", "gpll" }; | ||
167 | PNAME(mux_pciecore_cru_phy_p) = { "clk_pcie_core_cru", | ||
168 | "clk_pcie_core_phy" }; | ||
169 | |||
170 | PNAME(mux_aclk_emmc_p) = { "cpll_aclk_emmc_src", | ||
171 | "gpll_aclk_emmc_src" }; | ||
172 | |||
173 | PNAME(mux_aclk_perilp0_p) = { "cpll_aclk_perilp0_src", | ||
174 | "gpll_aclk_perilp0_src" }; | ||
175 | |||
176 | PNAME(mux_fclk_cm0s_p) = { "cpll_fclk_cm0s_src", | ||
177 | "gpll_fclk_cm0s_src" }; | ||
178 | |||
179 | PNAME(mux_hclk_perilp1_p) = { "cpll_hclk_perilp1_src", | ||
180 | "gpll_hclk_perilp1_src" }; | ||
181 | |||
182 | PNAME(mux_clk_testout1_p) = { "clk_testout1_pll_src", "xin24m" }; | ||
183 | PNAME(mux_clk_testout2_p) = { "clk_testout2_pll_src", "xin24m" }; | ||
184 | |||
185 | PNAME(mux_usbphy_480m_p) = { "clk_usbphy0_480m_src", | ||
186 | "clk_usbphy1_480m_src" }; | ||
187 | PNAME(mux_aclk_gmac_p) = { "cpll_aclk_gmac_src", | ||
188 | "gpll_aclk_gmac_src" }; | ||
189 | PNAME(mux_rmii_p) = { "clk_gmac", "clkin_gmac" }; | ||
190 | PNAME(mux_spdif_p) = { "clk_spdif_div", "clk_spdif_frac", | ||
191 | "clkin_i2s", "xin12m" }; | ||
192 | PNAME(mux_i2s0_p) = { "clk_i2s0_div", "clk_i2s0_frac", | ||
193 | "clkin_i2s", "xin12m" }; | ||
194 | PNAME(mux_i2s1_p) = { "clk_i2s1_div", "clk_i2s1_frac", | ||
195 | "clkin_i2s", "xin12m" }; | ||
196 | PNAME(mux_i2s2_p) = { "clk_i2s2_div", "clk_i2s2_frac", | ||
197 | "clkin_i2s", "xin12m" }; | ||
198 | PNAME(mux_i2sch_p) = { "clk_i2s0", "clk_i2s1", | ||
199 | "clk_i2s2" }; | ||
200 | PNAME(mux_i2sout_p) = { "clk_i2sout_src", "xin12m" }; | ||
201 | |||
202 | PNAME(mux_uart0_p) = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; | ||
203 | PNAME(mux_uart1_p) = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; | ||
204 | PNAME(mux_uart2_p) = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; | ||
205 | PNAME(mux_uart3_p) = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; | ||
206 | |||
207 | /* PMU CRU parents */ | ||
208 | PNAME(mux_ppll_24m_p) = { "ppll", "xin24m" }; | ||
209 | PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" }; | ||
210 | PNAME(mux_fclk_cm0s_pmu_ppll_p) = { "fclk_cm0s_pmu_ppll_src", "xin24m" }; | ||
211 | PNAME(mux_wifi_pmu_p) = { "clk_wifi_div", "clk_wifi_frac" }; | ||
212 | PNAME(mux_uart4_pmu_p) = { "clk_uart4_div", "clk_uart4_frac", | ||
213 | "xin24m" }; | ||
214 | PNAME(mux_clk_testout2_2io_p) = { "clk_testout2", "clk_32k_suspend_pmu" }; | ||
215 | |||
216 | static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = { | ||
217 | [lpll] = PLL(pll_rk3399, PLL_APLLL, "lpll", mux_pll_p, 0, RK3399_PLL_CON(0), | ||
218 | RK3399_PLL_CON(3), 8, 31, 0, rk3399_pll_rates), | ||
219 | [bpll] = PLL(pll_rk3399, PLL_APLLB, "bpll", mux_pll_p, 0, RK3399_PLL_CON(8), | ||
220 | RK3399_PLL_CON(11), 8, 31, 0, rk3399_pll_rates), | ||
221 | [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK3399_PLL_CON(16), | ||
222 | RK3399_PLL_CON(19), 8, 31, 0, NULL), | ||
223 | [cpll] = PLL(pll_rk3399, PLL_CPLL, "cpll", mux_pll_p, 0, RK3399_PLL_CON(24), | ||
224 | RK3399_PLL_CON(27), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), | ||
225 | [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK3399_PLL_CON(32), | ||
226 | RK3399_PLL_CON(35), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), | ||
227 | [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40), | ||
228 | RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), | ||
229 | [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48), | ||
230 | RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), | ||
231 | }; | ||
232 | |||
233 | static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = { | ||
234 | [ppll] = PLL(pll_rk3399, PLL_PPLL, "ppll", mux_pll_p, 0, RK3399_PMU_PLL_CON(0), | ||
235 | RK3399_PMU_PLL_CON(3), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates), | ||
236 | }; | ||
237 | |||
238 | #define MFLAGS CLK_MUX_HIWORD_MASK | ||
239 | #define DFLAGS CLK_DIVIDER_HIWORD_MASK | ||
240 | #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) | ||
241 | #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK | ||
242 | |||
243 | static struct rockchip_clk_branch rk3399_spdif_fracmux __initdata = | ||
244 | MUX(0, "clk_spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT, | ||
245 | RK3399_CLKSEL_CON(32), 13, 2, MFLAGS); | ||
246 | |||
247 | static struct rockchip_clk_branch rk3399_i2s0_fracmux __initdata = | ||
248 | MUX(0, "clk_i2s0_mux", mux_i2s0_p, CLK_SET_RATE_PARENT, | ||
249 | RK3399_CLKSEL_CON(28), 8, 2, MFLAGS); | ||
250 | |||
251 | static struct rockchip_clk_branch rk3399_i2s1_fracmux __initdata = | ||
252 | MUX(0, "clk_i2s1_mux", mux_i2s1_p, CLK_SET_RATE_PARENT, | ||
253 | RK3399_CLKSEL_CON(29), 8, 2, MFLAGS); | ||
254 | |||
255 | static struct rockchip_clk_branch rk3399_i2s2_fracmux __initdata = | ||
256 | MUX(0, "clk_i2s2_mux", mux_i2s2_p, CLK_SET_RATE_PARENT, | ||
257 | RK3399_CLKSEL_CON(30), 8, 2, MFLAGS); | ||
258 | |||
259 | static struct rockchip_clk_branch rk3399_uart0_fracmux __initdata = | ||
260 | MUX(SCLK_UART0, "clk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, | ||
261 | RK3399_CLKSEL_CON(33), 8, 2, MFLAGS); | ||
262 | |||
263 | static struct rockchip_clk_branch rk3399_uart1_fracmux __initdata = | ||
264 | MUX(SCLK_UART1, "clk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, | ||
265 | RK3399_CLKSEL_CON(34), 8, 2, MFLAGS); | ||
266 | |||
267 | static struct rockchip_clk_branch rk3399_uart2_fracmux __initdata = | ||
268 | MUX(SCLK_UART2, "clk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, | ||
269 | RK3399_CLKSEL_CON(35), 8, 2, MFLAGS); | ||
270 | |||
271 | static struct rockchip_clk_branch rk3399_uart3_fracmux __initdata = | ||
272 | MUX(SCLK_UART3, "clk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT, | ||
273 | RK3399_CLKSEL_CON(36), 8, 2, MFLAGS); | ||
274 | |||
275 | static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata = | ||
276 | MUX(SCLK_UART4_PMU, "clk_uart4_pmu", mux_uart4_pmu_p, CLK_SET_RATE_PARENT, | ||
277 | RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS); | ||
278 | |||
279 | static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata = | ||
280 | MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT, | ||
281 | RK3399_CLKSEL_CON(49), 11, 1, MFLAGS); | ||
282 | |||
283 | static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata = | ||
284 | MUX(DCLK_VOP1, "dclk_vop1", mux_dclk_vop1_p, CLK_SET_RATE_PARENT, | ||
285 | RK3399_CLKSEL_CON(50), 11, 1, MFLAGS); | ||
286 | |||
287 | static struct rockchip_clk_branch rk3399_pmuclk_wifi_fracmux __initdata = | ||
288 | MUX(SCLK_WIFI_PMU, "clk_wifi_pmu", mux_wifi_pmu_p, CLK_SET_RATE_PARENT, | ||
289 | RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS); | ||
290 | |||
291 | static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = { | ||
292 | .core_reg = RK3399_CLKSEL_CON(0), | ||
293 | .div_core_shift = 0, | ||
294 | .div_core_mask = 0x1f, | ||
295 | .mux_core_alt = 3, | ||
296 | .mux_core_main = 0, | ||
297 | .mux_core_shift = 6, | ||
298 | .mux_core_mask = 0x3, | ||
299 | }; | ||
300 | |||
301 | static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = { | ||
302 | .core_reg = RK3399_CLKSEL_CON(2), | ||
303 | .div_core_shift = 0, | ||
304 | .div_core_mask = 0x1f, | ||
305 | .mux_core_alt = 3, | ||
306 | .mux_core_main = 1, | ||
307 | .mux_core_shift = 6, | ||
308 | .mux_core_mask = 0x3, | ||
309 | }; | ||
310 | |||
311 | #define RK3399_DIV_ACLKM_MASK 0x1f | ||
312 | #define RK3399_DIV_ACLKM_SHIFT 8 | ||
313 | #define RK3399_DIV_ATCLK_MASK 0x1f | ||
314 | #define RK3399_DIV_ATCLK_SHIFT 0 | ||
315 | #define RK3399_DIV_PCLK_DBG_MASK 0x1f | ||
316 | #define RK3399_DIV_PCLK_DBG_SHIFT 8 | ||
317 | |||
318 | #define RK3399_CLKSEL0(_offs, _aclkm) \ | ||
319 | { \ | ||
320 | .reg = RK3399_CLKSEL_CON(0 + _offs), \ | ||
321 | .val = HIWORD_UPDATE(_aclkm, RK3399_DIV_ACLKM_MASK, \ | ||
322 | RK3399_DIV_ACLKM_SHIFT), \ | ||
323 | } | ||
324 | #define RK3399_CLKSEL1(_offs, _atclk, _pdbg) \ | ||
325 | { \ | ||
326 | .reg = RK3399_CLKSEL_CON(1 + _offs), \ | ||
327 | .val = HIWORD_UPDATE(_atclk, RK3399_DIV_ATCLK_MASK, \ | ||
328 | RK3399_DIV_ATCLK_SHIFT) | \ | ||
329 | HIWORD_UPDATE(_pdbg, RK3399_DIV_PCLK_DBG_MASK, \ | ||
330 | RK3399_DIV_PCLK_DBG_SHIFT), \ | ||
331 | } | ||
332 | |||
333 | /* cluster_l: aclkm in clksel0, rest in clksel1 */ | ||
334 | #define RK3399_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg) \ | ||
335 | { \ | ||
336 | .prate = _prate##U, \ | ||
337 | .divs = { \ | ||
338 | RK3399_CLKSEL0(0, _aclkm), \ | ||
339 | RK3399_CLKSEL1(0, _atclk, _pdbg), \ | ||
340 | }, \ | ||
341 | } | ||
342 | |||
343 | /* cluster_b: aclkm in clksel2, rest in clksel3 */ | ||
344 | #define RK3399_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg) \ | ||
345 | { \ | ||
346 | .prate = _prate##U, \ | ||
347 | .divs = { \ | ||
348 | RK3399_CLKSEL0(2, _aclkm), \ | ||
349 | RK3399_CLKSEL1(2, _atclk, _pdbg), \ | ||
350 | }, \ | ||
351 | } | ||
352 | |||
353 | static struct rockchip_cpuclk_rate_table rk3399_cpuclkl_rates[] __initdata = { | ||
354 | RK3399_CPUCLKL_RATE(1800000000, 1, 8, 8), | ||
355 | RK3399_CPUCLKL_RATE(1704000000, 1, 8, 8), | ||
356 | RK3399_CPUCLKL_RATE(1608000000, 1, 7, 7), | ||
357 | RK3399_CPUCLKL_RATE(1512000000, 1, 7, 7), | ||
358 | RK3399_CPUCLKL_RATE(1488000000, 1, 6, 6), | ||
359 | RK3399_CPUCLKL_RATE(1416000000, 1, 6, 6), | ||
360 | RK3399_CPUCLKL_RATE(1200000000, 1, 5, 5), | ||
361 | RK3399_CPUCLKL_RATE(1008000000, 1, 5, 5), | ||
362 | RK3399_CPUCLKL_RATE( 816000000, 1, 4, 4), | ||
363 | RK3399_CPUCLKL_RATE( 696000000, 1, 3, 3), | ||
364 | RK3399_CPUCLKL_RATE( 600000000, 1, 3, 3), | ||
365 | RK3399_CPUCLKL_RATE( 408000000, 1, 2, 2), | ||
366 | RK3399_CPUCLKL_RATE( 312000000, 1, 1, 1), | ||
367 | RK3399_CPUCLKL_RATE( 216000000, 1, 1, 1), | ||
368 | RK3399_CPUCLKL_RATE( 96000000, 1, 1, 1), | ||
369 | }; | ||
370 | |||
371 | static struct rockchip_cpuclk_rate_table rk3399_cpuclkb_rates[] __initdata = { | ||
372 | RK3399_CPUCLKB_RATE(2208000000, 1, 11, 11), | ||
373 | RK3399_CPUCLKB_RATE(2184000000, 1, 11, 11), | ||
374 | RK3399_CPUCLKB_RATE(2088000000, 1, 10, 10), | ||
375 | RK3399_CPUCLKB_RATE(2040000000, 1, 10, 10), | ||
376 | RK3399_CPUCLKB_RATE(1992000000, 1, 9, 9), | ||
377 | RK3399_CPUCLKB_RATE(1896000000, 1, 9, 9), | ||
378 | RK3399_CPUCLKB_RATE(1800000000, 1, 8, 8), | ||
379 | RK3399_CPUCLKB_RATE(1704000000, 1, 8, 8), | ||
380 | RK3399_CPUCLKB_RATE(1608000000, 1, 7, 7), | ||
381 | RK3399_CPUCLKB_RATE(1512000000, 1, 7, 7), | ||
382 | RK3399_CPUCLKB_RATE(1488000000, 1, 6, 6), | ||
383 | RK3399_CPUCLKB_RATE(1416000000, 1, 6, 6), | ||
384 | RK3399_CPUCLKB_RATE(1200000000, 1, 5, 5), | ||
385 | RK3399_CPUCLKB_RATE(1008000000, 1, 5, 5), | ||
386 | RK3399_CPUCLKB_RATE( 816000000, 1, 4, 4), | ||
387 | RK3399_CPUCLKB_RATE( 696000000, 1, 3, 3), | ||
388 | RK3399_CPUCLKB_RATE( 600000000, 1, 3, 3), | ||
389 | RK3399_CPUCLKB_RATE( 408000000, 1, 2, 2), | ||
390 | RK3399_CPUCLKB_RATE( 312000000, 1, 1, 1), | ||
391 | RK3399_CPUCLKB_RATE( 216000000, 1, 1, 1), | ||
392 | RK3399_CPUCLKB_RATE( 96000000, 1, 1, 1), | ||
393 | }; | ||
394 | |||
395 | static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { | ||
396 | /* | ||
397 | * CRU Clock-Architecture | ||
398 | */ | ||
399 | |||
400 | /* usbphy */ | ||
401 | GATE(SCLK_USB2PHY0_REF, "clk_usb2phy0_ref", "xin24m", CLK_IGNORE_UNUSED, | ||
402 | RK3399_CLKGATE_CON(6), 5, GFLAGS), | ||
403 | GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED, | ||
404 | RK3399_CLKGATE_CON(6), 6, GFLAGS), | ||
405 | |||
406 | GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED, | ||
407 | RK3399_CLKGATE_CON(13), 12, GFLAGS), | ||
408 | GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED, | ||
409 | RK3399_CLKGATE_CON(13), 12, GFLAGS), | ||
410 | MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED, | ||
411 | RK3399_CLKSEL_CON(14), 6, 1, MFLAGS), | ||
412 | |||
413 | MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0, | ||
414 | RK3399_CLKSEL_CON(14), 15, 1, MFLAGS), | ||
415 | |||
416 | COMPOSITE_NODIV(SCLK_HSICPHY, "clk_hsicphy", mux_pll_src_cpll_gpll_npll_usbphy480m_p, 0, | ||
417 | RK3399_CLKSEL_CON(19), 0, 2, MFLAGS, | ||
418 | RK3399_CLKGATE_CON(6), 4, GFLAGS), | ||
419 | |||
420 | COMPOSITE(ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_p, 0, | ||
421 | RK3399_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
422 | RK3399_CLKGATE_CON(12), 0, GFLAGS), | ||
423 | GATE(ACLK_USB3_NOC, "aclk_usb3_noc", "aclk_usb3", CLK_IGNORE_UNUSED, | ||
424 | RK3399_CLKGATE_CON(30), 0, GFLAGS), | ||
425 | GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", 0, | ||
426 | RK3399_CLKGATE_CON(30), 1, GFLAGS), | ||
427 | GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", 0, | ||
428 | RK3399_CLKGATE_CON(30), 2, GFLAGS), | ||
429 | GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", 0, | ||
430 | RK3399_CLKGATE_CON(30), 3, GFLAGS), | ||
431 | GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", 0, | ||
432 | RK3399_CLKGATE_CON(30), 4, GFLAGS), | ||
433 | |||
434 | GATE(SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 0, | ||
435 | RK3399_CLKGATE_CON(12), 1, GFLAGS), | ||
436 | GATE(SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 0, | ||
437 | RK3399_CLKGATE_CON(12), 2, GFLAGS), | ||
438 | |||
439 | COMPOSITE(SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", mux_pll_p, 0, | ||
440 | RK3399_CLKSEL_CON(40), 15, 1, MFLAGS, 0, 10, DFLAGS, | ||
441 | RK3399_CLKGATE_CON(12), 3, GFLAGS), | ||
442 | |||
443 | COMPOSITE(SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", mux_pll_p, 0, | ||
444 | RK3399_CLKSEL_CON(41), 15, 1, MFLAGS, 0, 10, DFLAGS, | ||
445 | RK3399_CLKGATE_CON(12), 4, GFLAGS), | ||
446 | |||
447 | COMPOSITE(SCLK_UPHY0_TCPDPHY_REF, "clk_uphy0_tcpdphy_ref", mux_pll_p, 0, | ||
448 | RK3399_CLKSEL_CON(64), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
449 | RK3399_CLKGATE_CON(13), 4, GFLAGS), | ||
450 | |||
451 | COMPOSITE(SCLK_UPHY0_TCPDCORE, "clk_uphy0_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0, | ||
452 | RK3399_CLKSEL_CON(64), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
453 | RK3399_CLKGATE_CON(13), 5, GFLAGS), | ||
454 | |||
455 | COMPOSITE(SCLK_UPHY1_TCPDPHY_REF, "clk_uphy1_tcpdphy_ref", mux_pll_p, 0, | ||
456 | RK3399_CLKSEL_CON(65), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
457 | RK3399_CLKGATE_CON(13), 6, GFLAGS), | ||
458 | |||
459 | COMPOSITE(SCLK_UPHY1_TCPDCORE, "clk_uphy1_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0, | ||
460 | RK3399_CLKSEL_CON(65), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
461 | RK3399_CLKGATE_CON(13), 7, GFLAGS), | ||
462 | |||
463 | /* little core */ | ||
464 | GATE(0, "clk_core_l_lpll_src", "lpll", CLK_IGNORE_UNUSED, | ||
465 | RK3399_CLKGATE_CON(0), 0, GFLAGS), | ||
466 | GATE(0, "clk_core_l_bpll_src", "bpll", CLK_IGNORE_UNUSED, | ||
467 | RK3399_CLKGATE_CON(0), 1, GFLAGS), | ||
468 | GATE(0, "clk_core_l_dpll_src", "dpll", CLK_IGNORE_UNUSED, | ||
469 | RK3399_CLKGATE_CON(0), 2, GFLAGS), | ||
470 | GATE(0, "clk_core_l_gpll_src", "gpll", CLK_IGNORE_UNUSED, | ||
471 | RK3399_CLKGATE_CON(0), 3, GFLAGS), | ||
472 | |||
473 | COMPOSITE_NOMUX(0, "aclkm_core_l", "armclkl", CLK_IGNORE_UNUSED, | ||
474 | RK3399_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
475 | RK3399_CLKGATE_CON(0), 4, GFLAGS), | ||
476 | COMPOSITE_NOMUX(0, "atclk_core_l", "armclkl", CLK_IGNORE_UNUSED, | ||
477 | RK3399_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
478 | RK3399_CLKGATE_CON(0), 5, GFLAGS), | ||
479 | COMPOSITE_NOMUX(0, "pclk_dbg_core_l", "armclkl", CLK_IGNORE_UNUSED, | ||
480 | RK3399_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
481 | RK3399_CLKGATE_CON(0), 6, GFLAGS), | ||
482 | |||
483 | GATE(ACLK_CORE_ADB400_CORE_L_2_CCI500, "aclk_core_adb400_core_l_2_cci500", "aclkm_core_l", CLK_IGNORE_UNUSED, | ||
484 | RK3399_CLKGATE_CON(14), 12, GFLAGS), | ||
485 | GATE(ACLK_PERF_CORE_L, "aclk_perf_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED, | ||
486 | RK3399_CLKGATE_CON(14), 13, GFLAGS), | ||
487 | |||
488 | GATE(0, "clk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED, | ||
489 | RK3399_CLKGATE_CON(14), 9, GFLAGS), | ||
490 | GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_core_adb400_gic_2_core_l", "armclkl", CLK_IGNORE_UNUSED, | ||
491 | RK3399_CLKGATE_CON(14), 10, GFLAGS), | ||
492 | GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED, | ||
493 | RK3399_CLKGATE_CON(14), 11, GFLAGS), | ||
494 | GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED, | ||
495 | RK3399_CLKGATE_CON(0), 7, GFLAGS), | ||
496 | |||
497 | /* big core */ | ||
498 | GATE(0, "clk_core_b_lpll_src", "lpll", CLK_IGNORE_UNUSED, | ||
499 | RK3399_CLKGATE_CON(1), 0, GFLAGS), | ||
500 | GATE(0, "clk_core_b_bpll_src", "bpll", CLK_IGNORE_UNUSED, | ||
501 | RK3399_CLKGATE_CON(1), 1, GFLAGS), | ||
502 | GATE(0, "clk_core_b_dpll_src", "dpll", CLK_IGNORE_UNUSED, | ||
503 | RK3399_CLKGATE_CON(1), 2, GFLAGS), | ||
504 | GATE(0, "clk_core_b_gpll_src", "gpll", CLK_IGNORE_UNUSED, | ||
505 | RK3399_CLKGATE_CON(1), 3, GFLAGS), | ||
506 | |||
507 | COMPOSITE_NOMUX(0, "aclkm_core_b", "armclkb", CLK_IGNORE_UNUSED, | ||
508 | RK3399_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
509 | RK3399_CLKGATE_CON(1), 4, GFLAGS), | ||
510 | COMPOSITE_NOMUX(0, "atclk_core_b", "armclkb", CLK_IGNORE_UNUSED, | ||
511 | RK3399_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
512 | RK3399_CLKGATE_CON(1), 5, GFLAGS), | ||
513 | COMPOSITE_NOMUX(0, "pclk_dbg_core_b", "armclkb", CLK_IGNORE_UNUSED, | ||
514 | RK3399_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
515 | RK3399_CLKGATE_CON(1), 6, GFLAGS), | ||
516 | |||
517 | GATE(ACLK_CORE_ADB400_CORE_B_2_CCI500, "aclk_core_adb400_core_b_2_cci500", "aclkm_core_b", CLK_IGNORE_UNUSED, | ||
518 | RK3399_CLKGATE_CON(14), 5, GFLAGS), | ||
519 | GATE(ACLK_PERF_CORE_B, "aclk_perf_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED, | ||
520 | RK3399_CLKGATE_CON(14), 6, GFLAGS), | ||
521 | |||
522 | GATE(0, "clk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED, | ||
523 | RK3399_CLKGATE_CON(14), 1, GFLAGS), | ||
524 | GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_core_adb400_gic_2_core_b", "armclkb", CLK_IGNORE_UNUSED, | ||
525 | RK3399_CLKGATE_CON(14), 3, GFLAGS), | ||
526 | GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_core_adb400_core_b_2_gic", "armclkb", CLK_IGNORE_UNUSED, | ||
527 | RK3399_CLKGATE_CON(14), 4, GFLAGS), | ||
528 | |||
529 | DIV(0, "pclken_dbg_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, | ||
530 | RK3399_CLKSEL_CON(3), 13, 2, DFLAGS | CLK_DIVIDER_READ_ONLY), | ||
531 | |||
532 | GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED, | ||
533 | RK3399_CLKGATE_CON(14), 2, GFLAGS), | ||
534 | |||
535 | GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED, | ||
536 | RK3399_CLKGATE_CON(1), 7, GFLAGS), | ||
537 | |||
538 | /* gmac */ | ||
539 | GATE(0, "cpll_aclk_gmac_src", "cpll", CLK_IGNORE_UNUSED, | ||
540 | RK3399_CLKGATE_CON(6), 9, GFLAGS), | ||
541 | GATE(0, "gpll_aclk_gmac_src", "gpll", CLK_IGNORE_UNUSED, | ||
542 | RK3399_CLKGATE_CON(6), 8, GFLAGS), | ||
543 | COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_p, 0, | ||
544 | RK3399_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
545 | RK3399_CLKGATE_CON(6), 10, GFLAGS), | ||
546 | |||
547 | GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", 0, | ||
548 | RK3399_CLKGATE_CON(32), 0, GFLAGS), | ||
549 | GATE(ACLK_GMAC_NOC, "aclk_gmac_noc", "aclk_gmac_pre", CLK_IGNORE_UNUSED, | ||
550 | RK3399_CLKGATE_CON(32), 1, GFLAGS), | ||
551 | GATE(ACLK_PERF_GMAC, "aclk_perf_gmac", "aclk_gmac_pre", 0, | ||
552 | RK3399_CLKGATE_CON(32), 4, GFLAGS), | ||
553 | |||
554 | COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", 0, | ||
555 | RK3399_CLKSEL_CON(19), 8, 3, DFLAGS, | ||
556 | RK3399_CLKGATE_CON(6), 11, GFLAGS), | ||
557 | GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", 0, | ||
558 | RK3399_CLKGATE_CON(32), 2, GFLAGS), | ||
559 | GATE(PCLK_GMAC_NOC, "pclk_gmac_noc", "pclk_gmac_pre", CLK_IGNORE_UNUSED, | ||
560 | RK3399_CLKGATE_CON(32), 3, GFLAGS), | ||
561 | |||
562 | COMPOSITE(SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_p, 0, | ||
563 | RK3399_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
564 | RK3399_CLKGATE_CON(5), 5, GFLAGS), | ||
565 | |||
566 | MUX(SCLK_RMII_SRC, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT, | ||
567 | RK3399_CLKSEL_CON(19), 4, 1, MFLAGS), | ||
568 | GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", 0, | ||
569 | RK3399_CLKGATE_CON(5), 6, GFLAGS), | ||
570 | GATE(SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", 0, | ||
571 | RK3399_CLKGATE_CON(5), 7, GFLAGS), | ||
572 | GATE(SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", 0, | ||
573 | RK3399_CLKGATE_CON(5), 8, GFLAGS), | ||
574 | GATE(SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", 0, | ||
575 | RK3399_CLKGATE_CON(5), 9, GFLAGS), | ||
576 | |||
577 | /* spdif */ | ||
578 | COMPOSITE(0, "clk_spdif_div", mux_pll_src_cpll_gpll_p, 0, | ||
579 | RK3399_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
580 | RK3399_CLKGATE_CON(8), 13, GFLAGS), | ||
581 | COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", CLK_SET_RATE_PARENT, | ||
582 | RK3399_CLKSEL_CON(99), 0, | ||
583 | RK3399_CLKGATE_CON(8), 14, GFLAGS, | ||
584 | &rk3399_spdif_fracmux), | ||
585 | GATE(SCLK_SPDIF_8CH, "clk_spdif", "clk_spdif_mux", CLK_SET_RATE_PARENT, | ||
586 | RK3399_CLKGATE_CON(8), 15, GFLAGS), | ||
587 | |||
588 | COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, 0, | ||
589 | RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 5, DFLAGS, | ||
590 | RK3399_CLKGATE_CON(10), 6, GFLAGS), | ||
591 | /* i2s */ | ||
592 | COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0, | ||
593 | RK3399_CLKSEL_CON(28), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
594 | RK3399_CLKGATE_CON(8), 3, GFLAGS), | ||
595 | COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", CLK_SET_RATE_PARENT, | ||
596 | RK3399_CLKSEL_CON(96), 0, | ||
597 | RK3399_CLKGATE_CON(8), 4, GFLAGS, | ||
598 | &rk3399_i2s0_fracmux), | ||
599 | GATE(SCLK_I2S0_8CH, "clk_i2s0", "clk_i2s0_mux", CLK_SET_RATE_PARENT, | ||
600 | RK3399_CLKGATE_CON(8), 5, GFLAGS), | ||
601 | |||
602 | COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, 0, | ||
603 | RK3399_CLKSEL_CON(29), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
604 | RK3399_CLKGATE_CON(8), 6, GFLAGS), | ||
605 | COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", CLK_SET_RATE_PARENT, | ||
606 | RK3399_CLKSEL_CON(97), 0, | ||
607 | RK3399_CLKGATE_CON(8), 7, GFLAGS, | ||
608 | &rk3399_i2s1_fracmux), | ||
609 | GATE(SCLK_I2S1_8CH, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT, | ||
610 | RK3399_CLKGATE_CON(8), 8, GFLAGS), | ||
611 | |||
612 | COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, 0, | ||
613 | RK3399_CLKSEL_CON(30), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
614 | RK3399_CLKGATE_CON(8), 9, GFLAGS), | ||
615 | COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", CLK_SET_RATE_PARENT, | ||
616 | RK3399_CLKSEL_CON(98), 0, | ||
617 | RK3399_CLKGATE_CON(8), 10, GFLAGS, | ||
618 | &rk3399_i2s2_fracmux), | ||
619 | GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT, | ||
620 | RK3399_CLKGATE_CON(8), 11, GFLAGS), | ||
621 | |||
622 | MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT, | ||
623 | RK3399_CLKSEL_CON(31), 0, 2, MFLAGS), | ||
624 | COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT, | ||
625 | RK3399_CLKSEL_CON(30), 8, 2, MFLAGS, | ||
626 | RK3399_CLKGATE_CON(8), 12, GFLAGS), | ||
627 | |||
628 | /* uart */ | ||
629 | MUX(0, "clk_uart0_src", mux_pll_src_cpll_gpll_upll_p, 0, | ||
630 | RK3399_CLKSEL_CON(33), 12, 2, MFLAGS), | ||
631 | COMPOSITE_NOMUX(0, "clk_uart0_div", "clk_uart0_src", 0, | ||
632 | RK3399_CLKSEL_CON(33), 0, 7, DFLAGS, | ||
633 | RK3399_CLKGATE_CON(9), 0, GFLAGS), | ||
634 | COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div", CLK_SET_RATE_PARENT, | ||
635 | RK3399_CLKSEL_CON(100), 0, | ||
636 | RK3399_CLKGATE_CON(9), 1, GFLAGS, | ||
637 | &rk3399_uart0_fracmux), | ||
638 | |||
639 | MUX(0, "clk_uart_src", mux_pll_src_cpll_gpll_p, 0, | ||
640 | RK3399_CLKSEL_CON(33), 15, 1, MFLAGS), | ||
641 | COMPOSITE_NOMUX(0, "clk_uart1_div", "clk_uart_src", 0, | ||
642 | RK3399_CLKSEL_CON(34), 0, 7, DFLAGS, | ||
643 | RK3399_CLKGATE_CON(9), 2, GFLAGS), | ||
644 | COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div", CLK_SET_RATE_PARENT, | ||
645 | RK3399_CLKSEL_CON(101), 0, | ||
646 | RK3399_CLKGATE_CON(9), 3, GFLAGS, | ||
647 | &rk3399_uart1_fracmux), | ||
648 | |||
649 | COMPOSITE_NOMUX(0, "clk_uart2_div", "clk_uart_src", 0, | ||
650 | RK3399_CLKSEL_CON(35), 0, 7, DFLAGS, | ||
651 | RK3399_CLKGATE_CON(9), 4, GFLAGS), | ||
652 | COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div", CLK_SET_RATE_PARENT, | ||
653 | RK3399_CLKSEL_CON(102), 0, | ||
654 | RK3399_CLKGATE_CON(9), 5, GFLAGS, | ||
655 | &rk3399_uart2_fracmux), | ||
656 | |||
657 | COMPOSITE_NOMUX(0, "clk_uart3_div", "clk_uart_src", 0, | ||
658 | RK3399_CLKSEL_CON(36), 0, 7, DFLAGS, | ||
659 | RK3399_CLKGATE_CON(9), 6, GFLAGS), | ||
660 | COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_div", CLK_SET_RATE_PARENT, | ||
661 | RK3399_CLKSEL_CON(103), 0, | ||
662 | RK3399_CLKGATE_CON(9), 7, GFLAGS, | ||
663 | &rk3399_uart3_fracmux), | ||
664 | |||
665 | COMPOSITE(0, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, | ||
666 | RK3399_CLKSEL_CON(6), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
667 | RK3399_CLKGATE_CON(3), 4, GFLAGS), | ||
668 | |||
669 | GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED, | ||
670 | RK3399_CLKGATE_CON(18), 10, GFLAGS), | ||
671 | GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED, | ||
672 | RK3399_CLKGATE_CON(18), 12, GFLAGS), | ||
673 | GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED, | ||
674 | RK3399_CLKGATE_CON(18), 15, GFLAGS), | ||
675 | GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED, | ||
676 | RK3399_CLKGATE_CON(19), 2, GFLAGS), | ||
677 | |||
678 | GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED, | ||
679 | RK3399_CLKGATE_CON(4), 11, GFLAGS), | ||
680 | GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED, | ||
681 | RK3399_CLKGATE_CON(3), 5, GFLAGS), | ||
682 | GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED, | ||
683 | RK3399_CLKGATE_CON(3), 6, GFLAGS), | ||
684 | |||
685 | /* cci */ | ||
686 | GATE(0, "cpll_aclk_cci_src", "cpll", CLK_IGNORE_UNUSED, | ||
687 | RK3399_CLKGATE_CON(2), 0, GFLAGS), | ||
688 | GATE(0, "gpll_aclk_cci_src", "gpll", CLK_IGNORE_UNUSED, | ||
689 | RK3399_CLKGATE_CON(2), 1, GFLAGS), | ||
690 | GATE(0, "npll_aclk_cci_src", "npll", CLK_IGNORE_UNUSED, | ||
691 | RK3399_CLKGATE_CON(2), 2, GFLAGS), | ||
692 | GATE(0, "vpll_aclk_cci_src", "vpll", CLK_IGNORE_UNUSED, | ||
693 | RK3399_CLKGATE_CON(2), 3, GFLAGS), | ||
694 | |||
695 | COMPOSITE(0, "aclk_cci_pre", mux_aclk_cci_p, CLK_IGNORE_UNUSED, | ||
696 | RK3399_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
697 | RK3399_CLKGATE_CON(2), 4, GFLAGS), | ||
698 | |||
699 | GATE(ACLK_ADB400M_PD_CORE_L, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED, | ||
700 | RK3399_CLKGATE_CON(15), 0, GFLAGS), | ||
701 | GATE(ACLK_ADB400M_PD_CORE_B, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED, | ||
702 | RK3399_CLKGATE_CON(15), 1, GFLAGS), | ||
703 | GATE(ACLK_CCI, "aclk_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED, | ||
704 | RK3399_CLKGATE_CON(15), 2, GFLAGS), | ||
705 | GATE(ACLK_CCI_NOC0, "aclk_cci_noc0", "aclk_cci_pre", CLK_IGNORE_UNUSED, | ||
706 | RK3399_CLKGATE_CON(15), 3, GFLAGS), | ||
707 | GATE(ACLK_CCI_NOC1, "aclk_cci_noc1", "aclk_cci_pre", CLK_IGNORE_UNUSED, | ||
708 | RK3399_CLKGATE_CON(15), 4, GFLAGS), | ||
709 | GATE(ACLK_CCI_GRF, "aclk_cci_grf", "aclk_cci_pre", CLK_IGNORE_UNUSED, | ||
710 | RK3399_CLKGATE_CON(15), 7, GFLAGS), | ||
711 | |||
712 | GATE(0, "cpll_cci_trace", "cpll", CLK_IGNORE_UNUSED, | ||
713 | RK3399_CLKGATE_CON(2), 5, GFLAGS), | ||
714 | GATE(0, "gpll_cci_trace", "gpll", CLK_IGNORE_UNUSED, | ||
715 | RK3399_CLKGATE_CON(2), 6, GFLAGS), | ||
716 | COMPOSITE(SCLK_CCI_TRACE, "clk_cci_trace", mux_cci_trace_p, CLK_IGNORE_UNUSED, | ||
717 | RK3399_CLKSEL_CON(5), 15, 2, MFLAGS, 8, 5, DFLAGS, | ||
718 | RK3399_CLKGATE_CON(2), 7, GFLAGS), | ||
719 | |||
720 | GATE(0, "cpll_cs", "cpll", CLK_IGNORE_UNUSED, | ||
721 | RK3399_CLKGATE_CON(2), 8, GFLAGS), | ||
722 | GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED, | ||
723 | RK3399_CLKGATE_CON(2), 9, GFLAGS), | ||
724 | GATE(0, "npll_cs", "npll", CLK_IGNORE_UNUSED, | ||
725 | RK3399_CLKGATE_CON(2), 10, GFLAGS), | ||
726 | COMPOSITE_NOGATE(0, "clk_cs", mux_cs_p, CLK_IGNORE_UNUSED, | ||
727 | RK3399_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS), | ||
728 | GATE(0, "clk_dbg_cxcs", "clk_cs", CLK_IGNORE_UNUSED, | ||
729 | RK3399_CLKGATE_CON(15), 5, GFLAGS), | ||
730 | GATE(0, "clk_dbg_noc", "clk_cs", CLK_IGNORE_UNUSED, | ||
731 | RK3399_CLKGATE_CON(15), 6, GFLAGS), | ||
732 | |||
733 | /* vcodec */ | ||
734 | COMPOSITE(0, "aclk_vcodec_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, | ||
735 | RK3399_CLKSEL_CON(7), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
736 | RK3399_CLKGATE_CON(4), 0, GFLAGS), | ||
737 | COMPOSITE_NOMUX(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0, | ||
738 | RK3399_CLKSEL_CON(7), 8, 5, DFLAGS, | ||
739 | RK3399_CLKGATE_CON(4), 1, GFLAGS), | ||
740 | GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, | ||
741 | RK3399_CLKGATE_CON(17), 2, GFLAGS), | ||
742 | GATE(0, "hclk_vcodec_noc", "hclk_vcodec_pre", CLK_IGNORE_UNUSED, | ||
743 | RK3399_CLKGATE_CON(17), 3, GFLAGS), | ||
744 | |||
745 | GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0, | ||
746 | RK3399_CLKGATE_CON(17), 0, GFLAGS), | ||
747 | GATE(0, "aclk_vcodec_noc", "aclk_vcodec_pre", CLK_IGNORE_UNUSED, | ||
748 | RK3399_CLKGATE_CON(17), 1, GFLAGS), | ||
749 | |||
750 | /* vdu */ | ||
751 | COMPOSITE(SCLK_VDU_CORE, "clk_vdu_core", mux_pll_src_cpll_gpll_npll_p, 0, | ||
752 | RK3399_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
753 | RK3399_CLKGATE_CON(4), 4, GFLAGS), | ||
754 | COMPOSITE(SCLK_VDU_CA, "clk_vdu_ca", mux_pll_src_cpll_gpll_npll_p, 0, | ||
755 | RK3399_CLKSEL_CON(9), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
756 | RK3399_CLKGATE_CON(4), 5, GFLAGS), | ||
757 | |||
758 | COMPOSITE(0, "aclk_vdu_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, | ||
759 | RK3399_CLKSEL_CON(8), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
760 | RK3399_CLKGATE_CON(4), 2, GFLAGS), | ||
761 | COMPOSITE_NOMUX(0, "hclk_vdu_pre", "aclk_vdu_pre", 0, | ||
762 | RK3399_CLKSEL_CON(8), 8, 5, DFLAGS, | ||
763 | RK3399_CLKGATE_CON(4), 3, GFLAGS), | ||
764 | GATE(HCLK_VDU, "hclk_vdu", "hclk_vdu_pre", 0, | ||
765 | RK3399_CLKGATE_CON(17), 10, GFLAGS), | ||
766 | GATE(HCLK_VDU_NOC, "hclk_vdu_noc", "hclk_vdu_pre", CLK_IGNORE_UNUSED, | ||
767 | RK3399_CLKGATE_CON(17), 11, GFLAGS), | ||
768 | |||
769 | GATE(ACLK_VDU, "aclk_vdu", "aclk_vdu_pre", 0, | ||
770 | RK3399_CLKGATE_CON(17), 8, GFLAGS), | ||
771 | GATE(ACLK_VDU_NOC, "aclk_vdu_noc", "aclk_vdu_pre", CLK_IGNORE_UNUSED, | ||
772 | RK3399_CLKGATE_CON(17), 9, GFLAGS), | ||
773 | |||
774 | /* iep */ | ||
775 | COMPOSITE(0, "aclk_iep_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, | ||
776 | RK3399_CLKSEL_CON(10), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
777 | RK3399_CLKGATE_CON(4), 6, GFLAGS), | ||
778 | COMPOSITE_NOMUX(0, "hclk_iep_pre", "aclk_iep_pre", 0, | ||
779 | RK3399_CLKSEL_CON(10), 8, 5, DFLAGS, | ||
780 | RK3399_CLKGATE_CON(4), 7, GFLAGS), | ||
781 | GATE(HCLK_IEP, "hclk_iep", "hclk_iep_pre", 0, | ||
782 | RK3399_CLKGATE_CON(16), 2, GFLAGS), | ||
783 | GATE(HCLK_IEP_NOC, "hclk_iep_noc", "hclk_iep_pre", CLK_IGNORE_UNUSED, | ||
784 | RK3399_CLKGATE_CON(16), 3, GFLAGS), | ||
785 | |||
786 | GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0, | ||
787 | RK3399_CLKGATE_CON(16), 0, GFLAGS), | ||
788 | GATE(ACLK_IEP_NOC, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED, | ||
789 | RK3399_CLKGATE_CON(16), 1, GFLAGS), | ||
790 | |||
791 | /* rga */ | ||
792 | COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, 0, | ||
793 | RK3399_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
794 | RK3399_CLKGATE_CON(4), 10, GFLAGS), | ||
795 | |||
796 | COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0, | ||
797 | RK3399_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
798 | RK3399_CLKGATE_CON(4), 8, GFLAGS), | ||
799 | COMPOSITE_NOMUX(0, "hclk_rga_pre", "aclk_rga_pre", 0, | ||
800 | RK3399_CLKSEL_CON(11), 8, 5, DFLAGS, | ||
801 | RK3399_CLKGATE_CON(4), 9, GFLAGS), | ||
802 | GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 0, | ||
803 | RK3399_CLKGATE_CON(16), 10, GFLAGS), | ||
804 | GATE(HCLK_RGA_NOC, "hclk_rga_noc", "hclk_rga_pre", CLK_IGNORE_UNUSED, | ||
805 | RK3399_CLKGATE_CON(16), 11, GFLAGS), | ||
806 | |||
807 | GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, | ||
808 | RK3399_CLKGATE_CON(16), 8, GFLAGS), | ||
809 | GATE(ACLK_RGA_NOC, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, | ||
810 | RK3399_CLKGATE_CON(16), 9, GFLAGS), | ||
811 | |||
812 | /* center */ | ||
813 | COMPOSITE(0, "aclk_center", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, | ||
814 | RK3399_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
815 | RK3399_CLKGATE_CON(3), 7, GFLAGS), | ||
816 | GATE(ACLK_CENTER_MAIN_NOC, "aclk_center_main_noc", "aclk_center", CLK_IGNORE_UNUSED, | ||
817 | RK3399_CLKGATE_CON(19), 0, GFLAGS), | ||
818 | GATE(ACLK_CENTER_PERI_NOC, "aclk_center_peri_noc", "aclk_center", CLK_IGNORE_UNUSED, | ||
819 | RK3399_CLKGATE_CON(19), 1, GFLAGS), | ||
820 | |||
821 | /* gpu */ | ||
822 | COMPOSITE(0, "aclk_gpu_pre", mux_pll_src_ppll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED, | ||
823 | RK3399_CLKSEL_CON(13), 5, 3, MFLAGS, 0, 5, DFLAGS, | ||
824 | RK3399_CLKGATE_CON(13), 0, GFLAGS), | ||
825 | GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, | ||
826 | RK3399_CLKGATE_CON(30), 8, GFLAGS), | ||
827 | GATE(ACLK_PERF_GPU, "aclk_perf_gpu", "aclk_gpu_pre", 0, | ||
828 | RK3399_CLKGATE_CON(30), 10, GFLAGS), | ||
829 | GATE(ACLK_GPU_GRF, "aclk_gpu_grf", "aclk_gpu_pre", 0, | ||
830 | RK3399_CLKGATE_CON(30), 11, GFLAGS), | ||
831 | GATE(SCLK_PVTM_GPU, "aclk_pvtm_gpu", "xin24m", 0, | ||
832 | RK3399_CLKGATE_CON(13), 1, GFLAGS), | ||
833 | |||
834 | /* perihp */ | ||
835 | GATE(0, "cpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED, | ||
836 | RK3399_CLKGATE_CON(5), 0, GFLAGS), | ||
837 | GATE(0, "gpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED, | ||
838 | RK3399_CLKGATE_CON(5), 1, GFLAGS), | ||
839 | COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED, | ||
840 | RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
841 | RK3399_CLKGATE_CON(5), 2, GFLAGS), | ||
842 | COMPOSITE_NOMUX(HCLK_PERIHP, "hclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED, | ||
843 | RK3399_CLKSEL_CON(14), 8, 2, DFLAGS, | ||
844 | RK3399_CLKGATE_CON(5), 3, GFLAGS), | ||
845 | COMPOSITE_NOMUX(PCLK_PERIHP, "pclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED, | ||
846 | RK3399_CLKSEL_CON(14), 12, 2, DFLAGS, | ||
847 | RK3399_CLKGATE_CON(5), 4, GFLAGS), | ||
848 | |||
849 | GATE(ACLK_PERF_PCIE, "aclk_perf_pcie", "aclk_perihp", CLK_IGNORE_UNUSED, | ||
850 | RK3399_CLKGATE_CON(20), 2, GFLAGS), | ||
851 | GATE(ACLK_PCIE, "aclk_pcie", "aclk_perihp", CLK_IGNORE_UNUSED, | ||
852 | RK3399_CLKGATE_CON(20), 10, GFLAGS), | ||
853 | GATE(0, "aclk_perihp_noc", "aclk_perihp", CLK_IGNORE_UNUSED, | ||
854 | RK3399_CLKGATE_CON(20), 12, GFLAGS), | ||
855 | |||
856 | GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", 0, | ||
857 | RK3399_CLKGATE_CON(20), 5, GFLAGS), | ||
858 | GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", 0, | ||
859 | RK3399_CLKGATE_CON(20), 6, GFLAGS), | ||
860 | GATE(HCLK_HOST1, "hclk_host1", "hclk_perihp", 0, | ||
861 | RK3399_CLKGATE_CON(20), 7, GFLAGS), | ||
862 | GATE(HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", 0, | ||
863 | RK3399_CLKGATE_CON(20), 8, GFLAGS), | ||
864 | GATE(HCLK_HSIC, "hclk_hsic", "hclk_perihp", 0, | ||
865 | RK3399_CLKGATE_CON(20), 9, GFLAGS), | ||
866 | GATE(0, "hclk_perihp_noc", "hclk_perihp", CLK_IGNORE_UNUSED, | ||
867 | RK3399_CLKGATE_CON(20), 13, GFLAGS), | ||
868 | GATE(0, "hclk_ahb1tom", "hclk_perihp", CLK_IGNORE_UNUSED, | ||
869 | RK3399_CLKGATE_CON(20), 15, GFLAGS), | ||
870 | |||
871 | GATE(PCLK_PERIHP_GRF, "pclk_perihp_grf", "pclk_perihp", CLK_IGNORE_UNUSED, | ||
872 | RK3399_CLKGATE_CON(20), 4, GFLAGS), | ||
873 | GATE(PCLK_PCIE, "pclk_pcie", "pclk_perihp", 0, | ||
874 | RK3399_CLKGATE_CON(20), 11, GFLAGS), | ||
875 | GATE(0, "pclk_perihp_noc", "pclk_perihp", CLK_IGNORE_UNUSED, | ||
876 | RK3399_CLKGATE_CON(20), 14, GFLAGS), | ||
877 | GATE(PCLK_HSICPHY, "pclk_hsicphy", "pclk_perihp", 0, | ||
878 | RK3399_CLKGATE_CON(31), 8, GFLAGS), | ||
879 | |||
880 | /* sdio & sdmmc */ | ||
881 | COMPOSITE(0, "hclk_sd", mux_pll_src_cpll_gpll_p, 0, | ||
882 | RK3399_CLKSEL_CON(13), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
883 | RK3399_CLKGATE_CON(12), 13, GFLAGS), | ||
884 | GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", 0, | ||
885 | RK3399_CLKGATE_CON(33), 8, GFLAGS), | ||
886 | GATE(0, "hclk_sdmmc_noc", "hclk_sd", CLK_IGNORE_UNUSED, | ||
887 | RK3399_CLKGATE_CON(33), 9, GFLAGS), | ||
888 | |||
889 | COMPOSITE(SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0, | ||
890 | RK3399_CLKSEL_CON(15), 8, 3, MFLAGS, 0, 7, DFLAGS, | ||
891 | RK3399_CLKGATE_CON(6), 0, GFLAGS), | ||
892 | |||
893 | COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0, | ||
894 | RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS, | ||
895 | RK3399_CLKGATE_CON(6), 1, GFLAGS), | ||
896 | |||
897 | MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", RK3399_SDMMC_CON0, 1), | ||
898 | MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1), | ||
899 | |||
900 | MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", RK3399_SDIO_CON0, 1), | ||
901 | MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", RK3399_SDIO_CON1, 1), | ||
902 | |||
903 | /* pcie */ | ||
904 | COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0, | ||
905 | RK3399_CLKSEL_CON(17), 8, 3, MFLAGS, 0, 7, DFLAGS, | ||
906 | RK3399_CLKGATE_CON(6), 2, GFLAGS), | ||
907 | |||
908 | COMPOSITE_NOMUX(SCLK_PCIEPHY_REF100M, "clk_pciephy_ref100m", "npll", 0, | ||
909 | RK3399_CLKSEL_CON(18), 11, 5, DFLAGS, | ||
910 | RK3399_CLKGATE_CON(12), 6, GFLAGS), | ||
911 | MUX(SCLK_PCIEPHY_REF, "clk_pciephy_ref", mux_pll_src_24m_pciephy_p, CLK_SET_RATE_PARENT, | ||
912 | RK3399_CLKSEL_CON(18), 10, 1, MFLAGS), | ||
913 | |||
914 | COMPOSITE(0, "clk_pcie_core_cru", mux_pll_src_cpll_gpll_npll_p, 0, | ||
915 | RK3399_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 7, DFLAGS, | ||
916 | RK3399_CLKGATE_CON(6), 3, GFLAGS), | ||
917 | MUX(SCLK_PCIE_CORE, "clk_pcie_core", mux_pciecore_cru_phy_p, CLK_SET_RATE_PARENT, | ||
918 | RK3399_CLKSEL_CON(18), 7, 1, MFLAGS), | ||
919 | |||
920 | /* emmc */ | ||
921 | COMPOSITE(SCLK_EMMC, "clk_emmc", mux_pll_src_cpll_gpll_npll_upll_24m_p, 0, | ||
922 | RK3399_CLKSEL_CON(22), 8, 3, MFLAGS, 0, 7, DFLAGS, | ||
923 | RK3399_CLKGATE_CON(6), 14, GFLAGS), | ||
924 | |||
925 | GATE(0, "cpll_aclk_emmc_src", "cpll", CLK_IGNORE_UNUSED, | ||
926 | RK3399_CLKGATE_CON(6), 12, GFLAGS), | ||
927 | GATE(0, "gpll_aclk_emmc_src", "gpll", CLK_IGNORE_UNUSED, | ||
928 | RK3399_CLKGATE_CON(6), 13, GFLAGS), | ||
929 | COMPOSITE_NOGATE(ACLK_EMMC, "aclk_emmc", mux_aclk_emmc_p, CLK_IGNORE_UNUSED, | ||
930 | RK3399_CLKSEL_CON(21), 7, 1, MFLAGS, 0, 5, DFLAGS), | ||
931 | GATE(ACLK_EMMC_CORE, "aclk_emmccore", "aclk_emmc", CLK_IGNORE_UNUSED, | ||
932 | RK3399_CLKGATE_CON(32), 8, GFLAGS), | ||
933 | GATE(ACLK_EMMC_NOC, "aclk_emmc_noc", "aclk_emmc", CLK_IGNORE_UNUSED, | ||
934 | RK3399_CLKGATE_CON(32), 9, GFLAGS), | ||
935 | GATE(ACLK_EMMC_GRF, "aclk_emmcgrf", "aclk_emmc", CLK_IGNORE_UNUSED, | ||
936 | RK3399_CLKGATE_CON(32), 10, GFLAGS), | ||
937 | |||
938 | /* perilp0 */ | ||
939 | GATE(0, "cpll_aclk_perilp0_src", "cpll", CLK_IGNORE_UNUSED, | ||
940 | RK3399_CLKGATE_CON(7), 1, GFLAGS), | ||
941 | GATE(0, "gpll_aclk_perilp0_src", "gpll", CLK_IGNORE_UNUSED, | ||
942 | RK3399_CLKGATE_CON(7), 0, GFLAGS), | ||
943 | COMPOSITE(ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_p, CLK_IGNORE_UNUSED, | ||
944 | RK3399_CLKSEL_CON(23), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
945 | RK3399_CLKGATE_CON(7), 2, GFLAGS), | ||
946 | COMPOSITE_NOMUX(HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0", CLK_IGNORE_UNUSED, | ||
947 | RK3399_CLKSEL_CON(23), 8, 2, DFLAGS, | ||
948 | RK3399_CLKGATE_CON(7), 3, GFLAGS), | ||
949 | COMPOSITE_NOMUX(PCLK_PERILP0, "pclk_perilp0", "aclk_perilp0", 0, | ||
950 | RK3399_CLKSEL_CON(23), 12, 3, DFLAGS, | ||
951 | RK3399_CLKGATE_CON(7), 4, GFLAGS), | ||
952 | |||
953 | /* aclk_perilp0 gates */ | ||
954 | GATE(ACLK_INTMEM, "aclk_intmem", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 0, GFLAGS), | ||
955 | GATE(ACLK_TZMA, "aclk_tzma", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 1, GFLAGS), | ||
956 | GATE(SCLK_INTMEM0, "clk_intmem0", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 2, GFLAGS), | ||
957 | GATE(SCLK_INTMEM1, "clk_intmem1", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 3, GFLAGS), | ||
958 | GATE(SCLK_INTMEM2, "clk_intmem2", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 4, GFLAGS), | ||
959 | GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS), | ||
960 | GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS), | ||
961 | GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS), | ||
962 | GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS), | ||
963 | GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS), | ||
964 | GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS), | ||
965 | GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS), | ||
966 | |||
967 | /* hclk_perilp0 gates */ | ||
968 | GATE(HCLK_ROM, "hclk_rom", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 4, GFLAGS), | ||
969 | GATE(HCLK_M_CRYPTO0, "hclk_m_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 5, GFLAGS), | ||
970 | GATE(HCLK_S_CRYPTO0, "hclk_s_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 6, GFLAGS), | ||
971 | GATE(HCLK_M_CRYPTO1, "hclk_m_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 14, GFLAGS), | ||
972 | GATE(HCLK_S_CRYPTO1, "hclk_s_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 15, GFLAGS), | ||
973 | GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS), | ||
974 | |||
975 | /* pclk_perilp0 gates */ | ||
976 | GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS), | ||
977 | |||
978 | /* crypto */ | ||
979 | COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0, | ||
980 | RK3399_CLKSEL_CON(24), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
981 | RK3399_CLKGATE_CON(7), 7, GFLAGS), | ||
982 | |||
983 | COMPOSITE(SCLK_CRYPTO1, "clk_crypto1", mux_pll_src_cpll_gpll_ppll_p, 0, | ||
984 | RK3399_CLKSEL_CON(26), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
985 | RK3399_CLKGATE_CON(7), 8, GFLAGS), | ||
986 | |||
987 | /* cm0s_perilp */ | ||
988 | GATE(0, "cpll_fclk_cm0s_src", "cpll", 0, | ||
989 | RK3399_CLKGATE_CON(7), 6, GFLAGS), | ||
990 | GATE(0, "gpll_fclk_cm0s_src", "gpll", 0, | ||
991 | RK3399_CLKGATE_CON(7), 5, GFLAGS), | ||
992 | COMPOSITE(FCLK_CM0S, "fclk_cm0s", mux_fclk_cm0s_p, 0, | ||
993 | RK3399_CLKSEL_CON(24), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
994 | RK3399_CLKGATE_CON(7), 9, GFLAGS), | ||
995 | |||
996 | /* fclk_cm0s gates */ | ||
997 | GATE(SCLK_M0_PERILP, "sclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 8, GFLAGS), | ||
998 | GATE(HCLK_M0_PERILP, "hclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 9, GFLAGS), | ||
999 | GATE(DCLK_M0_PERILP, "dclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 10, GFLAGS), | ||
1000 | GATE(SCLK_M0_PERILP_DEC, "clk_m0_perilp_dec", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 11, GFLAGS), | ||
1001 | GATE(HCLK_M0_PERILP_NOC, "hclk_m0_perilp_noc", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 11, GFLAGS), | ||
1002 | |||
1003 | /* perilp1 */ | ||
1004 | GATE(0, "cpll_hclk_perilp1_src", "cpll", CLK_IGNORE_UNUSED, | ||
1005 | RK3399_CLKGATE_CON(8), 1, GFLAGS), | ||
1006 | GATE(0, "gpll_hclk_perilp1_src", "gpll", CLK_IGNORE_UNUSED, | ||
1007 | RK3399_CLKGATE_CON(8), 0, GFLAGS), | ||
1008 | COMPOSITE_NOGATE(HCLK_PERILP1, "hclk_perilp1", mux_hclk_perilp1_p, CLK_IGNORE_UNUSED, | ||
1009 | RK3399_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 5, DFLAGS), | ||
1010 | COMPOSITE_NOMUX(PCLK_PERILP1, "pclk_perilp1", "hclk_perilp1", CLK_IGNORE_UNUSED, | ||
1011 | RK3399_CLKSEL_CON(25), 8, 3, DFLAGS, | ||
1012 | RK3399_CLKGATE_CON(8), 2, GFLAGS), | ||
1013 | |||
1014 | /* hclk_perilp1 gates */ | ||
1015 | GATE(0, "hclk_perilp1_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 9, GFLAGS), | ||
1016 | GATE(0, "hclk_sdio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 12, GFLAGS), | ||
1017 | GATE(HCLK_I2S0_8CH, "hclk_i2s0", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 0, GFLAGS), | ||
1018 | GATE(HCLK_I2S1_8CH, "hclk_i2s1", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 1, GFLAGS), | ||
1019 | GATE(HCLK_I2S2_8CH, "hclk_i2s2", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 2, GFLAGS), | ||
1020 | GATE(HCLK_SPDIF, "hclk_spdif", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 3, GFLAGS), | ||
1021 | GATE(HCLK_SDIO, "hclk_sdio", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 4, GFLAGS), | ||
1022 | GATE(PCLK_SPI5, "pclk_spi5", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 5, GFLAGS), | ||
1023 | GATE(0, "hclk_sdioaudio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 6, GFLAGS), | ||
1024 | |||
1025 | /* pclk_perilp1 gates */ | ||
1026 | GATE(PCLK_UART0, "pclk_uart0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 0, GFLAGS), | ||
1027 | GATE(PCLK_UART1, "pclk_uart1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 1, GFLAGS), | ||
1028 | GATE(PCLK_UART2, "pclk_uart2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 2, GFLAGS), | ||
1029 | GATE(PCLK_UART3, "pclk_uart3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 3, GFLAGS), | ||
1030 | GATE(PCLK_I2C7, "pclk_rki2c7", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 5, GFLAGS), | ||
1031 | GATE(PCLK_I2C1, "pclk_rki2c1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 6, GFLAGS), | ||
1032 | GATE(PCLK_I2C5, "pclk_rki2c5", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 7, GFLAGS), | ||
1033 | GATE(PCLK_I2C6, "pclk_rki2c6", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 8, GFLAGS), | ||
1034 | GATE(PCLK_I2C2, "pclk_rki2c2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 9, GFLAGS), | ||
1035 | GATE(PCLK_I2C3, "pclk_rki2c3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 10, GFLAGS), | ||
1036 | GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 11, GFLAGS), | ||
1037 | GATE(PCLK_SARADC, "pclk_saradc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 12, GFLAGS), | ||
1038 | GATE(PCLK_TSADC, "pclk_tsadc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 13, GFLAGS), | ||
1039 | GATE(PCLK_EFUSE1024NS, "pclk_efuse1024ns", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 14, GFLAGS), | ||
1040 | GATE(PCLK_EFUSE1024S, "pclk_efuse1024s", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 15, GFLAGS), | ||
1041 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 10, GFLAGS), | ||
1042 | GATE(PCLK_SPI1, "pclk_spi1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 11, GFLAGS), | ||
1043 | GATE(PCLK_SPI2, "pclk_spi2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 12, GFLAGS), | ||
1044 | GATE(PCLK_SPI4, "pclk_spi4", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 13, GFLAGS), | ||
1045 | GATE(PCLK_PERIHP_GRF, "pclk_perilp_sgrf", "pclk_perilp1", 0, RK3399_CLKGATE_CON(24), 13, GFLAGS), | ||
1046 | GATE(0, "pclk_perilp1_noc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(25), 10, GFLAGS), | ||
1047 | |||
1048 | /* saradc */ | ||
1049 | COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 0, | ||
1050 | RK3399_CLKSEL_CON(26), 8, 8, DFLAGS, | ||
1051 | RK3399_CLKGATE_CON(9), 11, GFLAGS), | ||
1052 | |||
1053 | /* tsadc */ | ||
1054 | COMPOSITE(SCLK_TSADC, "clk_tsadc", mux_pll_p, 0, | ||
1055 | RK3399_CLKSEL_CON(27), 15, 1, MFLAGS, 0, 10, DFLAGS, | ||
1056 | RK3399_CLKGATE_CON(9), 10, GFLAGS), | ||
1057 | |||
1058 | /* cif_testout */ | ||
1059 | MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0, | ||
1060 | RK3399_CLKSEL_CON(38), 6, 2, MFLAGS), | ||
1061 | COMPOSITE(0, "clk_testout1", mux_clk_testout1_p, 0, | ||
1062 | RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS, | ||
1063 | RK3399_CLKGATE_CON(13), 14, GFLAGS), | ||
1064 | |||
1065 | MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0, | ||
1066 | RK3399_CLKSEL_CON(38), 14, 2, MFLAGS), | ||
1067 | COMPOSITE(0, "clk_testout2", mux_clk_testout2_p, 0, | ||
1068 | RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS, | ||
1069 | RK3399_CLKGATE_CON(13), 15, GFLAGS), | ||
1070 | |||
1071 | /* vio */ | ||
1072 | COMPOSITE(ACLK_VIO, "aclk_vio", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED, | ||
1073 | RK3399_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1074 | RK3399_CLKGATE_CON(11), 10, GFLAGS), | ||
1075 | COMPOSITE_NOMUX(PCLK_VIO, "pclk_vio", "aclk_vio", 0, | ||
1076 | RK3399_CLKSEL_CON(43), 0, 5, DFLAGS, | ||
1077 | RK3399_CLKGATE_CON(11), 1, GFLAGS), | ||
1078 | |||
1079 | GATE(ACLK_VIO_NOC, "aclk_vio_noc", "aclk_vio", CLK_IGNORE_UNUSED, | ||
1080 | RK3399_CLKGATE_CON(29), 0, GFLAGS), | ||
1081 | |||
1082 | GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "pclk_vio", 0, | ||
1083 | RK3399_CLKGATE_CON(29), 1, GFLAGS), | ||
1084 | GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "pclk_vio", 0, | ||
1085 | RK3399_CLKGATE_CON(29), 2, GFLAGS), | ||
1086 | GATE(PCLK_VIO_GRF, "pclk_vio_grf", "pclk_vio", CLK_IGNORE_UNUSED, | ||
1087 | RK3399_CLKGATE_CON(29), 12, GFLAGS), | ||
1088 | |||
1089 | /* hdcp */ | ||
1090 | COMPOSITE(ACLK_HDCP, "aclk_hdcp", mux_pll_src_cpll_gpll_ppll_p, 0, | ||
1091 | RK3399_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
1092 | RK3399_CLKGATE_CON(11), 12, GFLAGS), | ||
1093 | COMPOSITE_NOMUX(HCLK_HDCP, "hclk_hdcp", "aclk_hdcp", 0, | ||
1094 | RK3399_CLKSEL_CON(43), 5, 5, DFLAGS, | ||
1095 | RK3399_CLKGATE_CON(11), 3, GFLAGS), | ||
1096 | COMPOSITE_NOMUX(PCLK_HDCP, "pclk_hdcp", "aclk_hdcp", 0, | ||
1097 | RK3399_CLKSEL_CON(43), 10, 5, DFLAGS, | ||
1098 | RK3399_CLKGATE_CON(11), 10, GFLAGS), | ||
1099 | |||
1100 | GATE(ACLK_HDCP_NOC, "aclk_hdcp_noc", "aclk_hdcp", CLK_IGNORE_UNUSED, | ||
1101 | RK3399_CLKGATE_CON(29), 4, GFLAGS), | ||
1102 | GATE(ACLK_HDCP22, "aclk_hdcp22", "aclk_hdcp", 0, | ||
1103 | RK3399_CLKGATE_CON(29), 10, GFLAGS), | ||
1104 | |||
1105 | GATE(HCLK_HDCP_NOC, "hclk_hdcp_noc", "hclk_hdcp", CLK_IGNORE_UNUSED, | ||
1106 | RK3399_CLKGATE_CON(29), 5, GFLAGS), | ||
1107 | GATE(HCLK_HDCP22, "hclk_hdcp22", "hclk_hdcp", 0, | ||
1108 | RK3399_CLKGATE_CON(29), 9, GFLAGS), | ||
1109 | |||
1110 | GATE(PCLK_HDCP_NOC, "pclk_hdcp_noc", "pclk_hdcp", CLK_IGNORE_UNUSED, | ||
1111 | RK3399_CLKGATE_CON(29), 3, GFLAGS), | ||
1112 | GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_hdcp", 0, | ||
1113 | RK3399_CLKGATE_CON(29), 6, GFLAGS), | ||
1114 | GATE(PCLK_DP_CTRL, "pclk_dp_ctrl", "pclk_hdcp", 0, | ||
1115 | RK3399_CLKGATE_CON(29), 7, GFLAGS), | ||
1116 | GATE(PCLK_HDCP22, "pclk_hdcp22", "pclk_hdcp", 0, | ||
1117 | RK3399_CLKGATE_CON(29), 8, GFLAGS), | ||
1118 | GATE(PCLK_GASKET, "pclk_gasket", "pclk_hdcp", 0, | ||
1119 | RK3399_CLKGATE_CON(29), 11, GFLAGS), | ||
1120 | |||
1121 | /* edp */ | ||
1122 | COMPOSITE(SCLK_DP_CORE, "clk_dp_core", mux_pll_src_npll_cpll_gpll_p, 0, | ||
1123 | RK3399_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1124 | RK3399_CLKGATE_CON(11), 8, GFLAGS), | ||
1125 | |||
1126 | COMPOSITE(PCLK_EDP, "pclk_edp", mux_pll_src_cpll_gpll_p, 0, | ||
1127 | RK3399_CLKSEL_CON(44), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
1128 | RK3399_CLKGATE_CON(11), 11, GFLAGS), | ||
1129 | GATE(PCLK_EDP_NOC, "pclk_edp_noc", "pclk_edp", CLK_IGNORE_UNUSED, | ||
1130 | RK3399_CLKGATE_CON(32), 12, GFLAGS), | ||
1131 | GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_edp", 0, | ||
1132 | RK3399_CLKGATE_CON(32), 13, GFLAGS), | ||
1133 | |||
1134 | /* hdmi */ | ||
1135 | GATE(SCLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 0, | ||
1136 | RK3399_CLKGATE_CON(11), 6, GFLAGS), | ||
1137 | |||
1138 | COMPOSITE(SCLK_HDMI_CEC, "clk_hdmi_cec", mux_pll_p, 0, | ||
1139 | RK3399_CLKSEL_CON(45), 15, 1, MFLAGS, 0, 10, DFLAGS, | ||
1140 | RK3399_CLKGATE_CON(11), 7, GFLAGS), | ||
1141 | |||
1142 | /* vop0 */ | ||
1143 | COMPOSITE(ACLK_VOP0_PRE, "aclk_vop0_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0, | ||
1144 | RK3399_CLKSEL_CON(47), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1145 | RK3399_CLKGATE_CON(10), 8, GFLAGS), | ||
1146 | COMPOSITE_NOMUX(0, "hclk_vop0_pre", "aclk_vop0_pre", 0, | ||
1147 | RK3399_CLKSEL_CON(47), 8, 5, DFLAGS, | ||
1148 | RK3399_CLKGATE_CON(10), 9, GFLAGS), | ||
1149 | |||
1150 | GATE(ACLK_VOP0, "aclk_vop0", "aclk_vop0_pre", 0, | ||
1151 | RK3399_CLKGATE_CON(28), 3, GFLAGS), | ||
1152 | GATE(ACLK_VOP0_NOC, "aclk_vop0_noc", "aclk_vop0_pre", CLK_IGNORE_UNUSED, | ||
1153 | RK3399_CLKGATE_CON(28), 1, GFLAGS), | ||
1154 | |||
1155 | GATE(HCLK_VOP0, "hclk_vop0", "hclk_vop0_pre", 0, | ||
1156 | RK3399_CLKGATE_CON(28), 2, GFLAGS), | ||
1157 | GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED, | ||
1158 | RK3399_CLKGATE_CON(28), 0, GFLAGS), | ||
1159 | |||
1160 | COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0, | ||
1161 | RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS, | ||
1162 | RK3399_CLKGATE_CON(10), 12, GFLAGS), | ||
1163 | |||
1164 | COMPOSITE_FRACMUX_NOGATE(0, "dclk_vop0_frac", "dclk_vop0_div", CLK_SET_RATE_PARENT, | ||
1165 | RK3399_CLKSEL_CON(106), 0, | ||
1166 | &rk3399_dclk_vop0_fracmux), | ||
1167 | |||
1168 | COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, 0, | ||
1169 | RK3399_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1170 | RK3399_CLKGATE_CON(10), 14, GFLAGS), | ||
1171 | |||
1172 | /* vop1 */ | ||
1173 | COMPOSITE(ACLK_VOP1_PRE, "aclk_vop1_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0, | ||
1174 | RK3399_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1175 | RK3399_CLKGATE_CON(10), 10, GFLAGS), | ||
1176 | COMPOSITE_NOMUX(0, "hclk_vop1_pre", "aclk_vop1_pre", 0, | ||
1177 | RK3399_CLKSEL_CON(48), 8, 5, DFLAGS, | ||
1178 | RK3399_CLKGATE_CON(10), 11, GFLAGS), | ||
1179 | |||
1180 | GATE(ACLK_VOP1, "aclk_vop1", "aclk_vop1_pre", 0, | ||
1181 | RK3399_CLKGATE_CON(28), 7, GFLAGS), | ||
1182 | GATE(ACLK_VOP1_NOC, "aclk_vop1_noc", "aclk_vop1_pre", CLK_IGNORE_UNUSED, | ||
1183 | RK3399_CLKGATE_CON(28), 5, GFLAGS), | ||
1184 | |||
1185 | GATE(HCLK_VOP1, "hclk_vop1", "hclk_vop1_pre", 0, | ||
1186 | RK3399_CLKGATE_CON(28), 6, GFLAGS), | ||
1187 | GATE(HCLK_VOP1_NOC, "hclk_vop1_noc", "hclk_vop1_pre", CLK_IGNORE_UNUSED, | ||
1188 | RK3399_CLKGATE_CON(28), 4, GFLAGS), | ||
1189 | |||
1190 | COMPOSITE(DCLK_VOP1_DIV, "dclk_vop1_div", mux_pll_src_vpll_cpll_gpll_p, 0, | ||
1191 | RK3399_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 8, DFLAGS, | ||
1192 | RK3399_CLKGATE_CON(10), 13, GFLAGS), | ||
1193 | |||
1194 | COMPOSITE_FRACMUX_NOGATE(0, "dclk_vop1_frac", "dclk_vop1_div", CLK_SET_RATE_PARENT, | ||
1195 | RK3399_CLKSEL_CON(107), 0, | ||
1196 | &rk3399_dclk_vop1_fracmux), | ||
1197 | |||
1198 | COMPOSITE(SCLK_VOP1_PWM, "clk_vop1_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED, | ||
1199 | RK3399_CLKSEL_CON(52), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1200 | RK3399_CLKGATE_CON(10), 15, GFLAGS), | ||
1201 | |||
1202 | /* isp */ | ||
1203 | COMPOSITE(ACLK_ISP0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, 0, | ||
1204 | RK3399_CLKSEL_CON(53), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1205 | RK3399_CLKGATE_CON(12), 8, GFLAGS), | ||
1206 | COMPOSITE_NOMUX(HCLK_ISP0, "hclk_isp0", "aclk_isp0", 0, | ||
1207 | RK3399_CLKSEL_CON(53), 8, 5, DFLAGS, | ||
1208 | RK3399_CLKGATE_CON(12), 9, GFLAGS), | ||
1209 | |||
1210 | GATE(ACLK_ISP0_NOC, "aclk_isp0_noc", "aclk_isp0", CLK_IGNORE_UNUSED, | ||
1211 | RK3399_CLKGATE_CON(27), 1, GFLAGS), | ||
1212 | GATE(ACLK_ISP0_WRAPPER, "aclk_isp0_wrapper", "aclk_isp0", 0, | ||
1213 | RK3399_CLKGATE_CON(27), 5, GFLAGS), | ||
1214 | GATE(HCLK_ISP1_WRAPPER, "hclk_isp1_wrapper", "aclk_isp0", 0, | ||
1215 | RK3399_CLKGATE_CON(27), 7, GFLAGS), | ||
1216 | |||
1217 | GATE(HCLK_ISP0_NOC, "hclk_isp0_noc", "hclk_isp0", CLK_IGNORE_UNUSED, | ||
1218 | RK3399_CLKGATE_CON(27), 0, GFLAGS), | ||
1219 | GATE(HCLK_ISP0_WRAPPER, "hclk_isp0_wrapper", "hclk_isp0", 0, | ||
1220 | RK3399_CLKGATE_CON(27), 4, GFLAGS), | ||
1221 | |||
1222 | COMPOSITE(SCLK_ISP0, "clk_isp0", mux_pll_src_cpll_gpll_npll_p, 0, | ||
1223 | RK3399_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1224 | RK3399_CLKGATE_CON(11), 4, GFLAGS), | ||
1225 | |||
1226 | COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, 0, | ||
1227 | RK3399_CLKSEL_CON(54), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
1228 | RK3399_CLKGATE_CON(12), 10, GFLAGS), | ||
1229 | COMPOSITE_NOMUX(HCLK_ISP1, "hclk_isp1", "aclk_isp1", 0, | ||
1230 | RK3399_CLKSEL_CON(54), 8, 5, DFLAGS, | ||
1231 | RK3399_CLKGATE_CON(12), 11, GFLAGS), | ||
1232 | |||
1233 | GATE(ACLK_ISP1_NOC, "aclk_isp1_noc", "aclk_isp1", CLK_IGNORE_UNUSED, | ||
1234 | RK3399_CLKGATE_CON(27), 3, GFLAGS), | ||
1235 | |||
1236 | GATE(HCLK_ISP1_NOC, "hclk_isp1_noc", "hclk_isp1", CLK_IGNORE_UNUSED, | ||
1237 | RK3399_CLKGATE_CON(27), 2, GFLAGS), | ||
1238 | GATE(ACLK_ISP1_WRAPPER, "aclk_isp1_wrapper", "hclk_isp1", 0, | ||
1239 | RK3399_CLKGATE_CON(27), 8, GFLAGS), | ||
1240 | |||
1241 | COMPOSITE(SCLK_ISP1, "clk_isp1", mux_pll_src_cpll_gpll_npll_p, 0, | ||
1242 | RK3399_CLKSEL_CON(55), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
1243 | RK3399_CLKGATE_CON(11), 5, GFLAGS), | ||
1244 | |||
1245 | /* | ||
1246 | * We use pclkin_cifinv by default GRF_SOC_CON20[9] (GSC20_9) setting in system, | ||
1247 | * so we ignore the mux and make clocks nodes as following, | ||
1248 | * | ||
1249 | * pclkin_cifinv --|-------\ | ||
1250 | * |GSC20_9|-- pclkin_cifmux -- |G27_6| -- pclkin_isp1_wrapper | ||
1251 | * pclkin_cif --|-------/ | ||
1252 | */ | ||
1253 | GATE(PCLK_ISP1_WRAPPER, "pclkin_isp1_wrapper", "pclkin_cif", 0, | ||
1254 | RK3399_CLKGATE_CON(27), 6, GFLAGS), | ||
1255 | |||
1256 | /* cif */ | ||
1257 | COMPOSITE_NODIV(0, "clk_cifout_src", mux_pll_src_cpll_gpll_npll_p, 0, | ||
1258 | RK3399_CLKSEL_CON(56), 6, 2, MFLAGS, | ||
1259 | RK3399_CLKGATE_CON(10), 7, GFLAGS), | ||
1260 | |||
1261 | COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, 0, | ||
1262 | RK3399_CLKSEL_CON(56), 5, 1, MFLAGS, 0, 5, DFLAGS), | ||
1263 | |||
1264 | /* gic */ | ||
1265 | COMPOSITE(ACLK_GIC_PRE, "aclk_gic_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, | ||
1266 | RK3399_CLKSEL_CON(56), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
1267 | RK3399_CLKGATE_CON(12), 12, GFLAGS), | ||
1268 | |||
1269 | GATE(ACLK_GIC, "aclk_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 0, GFLAGS), | ||
1270 | GATE(ACLK_GIC_NOC, "aclk_gic_noc", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 1, GFLAGS), | ||
1271 | GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_gic_adb400_core_l_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 2, GFLAGS), | ||
1272 | GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_gic_adb400_core_b_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 3, GFLAGS), | ||
1273 | GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_gic_adb400_gic_2_core_l", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 4, GFLAGS), | ||
1274 | GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_gic_adb400_gic_2_core_b", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 5, GFLAGS), | ||
1275 | |||
1276 | /* alive */ | ||
1277 | /* pclk_alive_gpll_src is controlled by PMUGRF_SOC_CON0[6] */ | ||
1278 | DIV(PCLK_ALIVE, "pclk_alive", "gpll", 0, | ||
1279 | RK3399_CLKSEL_CON(57), 0, 5, DFLAGS), | ||
1280 | |||
1281 | GATE(PCLK_USBPHY_MUX_G, "pclk_usbphy_mux_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 4, GFLAGS), | ||
1282 | GATE(PCLK_UPHY0_TCPHY_G, "pclk_uphy0_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 5, GFLAGS), | ||
1283 | GATE(PCLK_UPHY0_TCPD_G, "pclk_uphy0_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 6, GFLAGS), | ||
1284 | GATE(PCLK_UPHY1_TCPHY_G, "pclk_uphy1_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 8, GFLAGS), | ||
1285 | GATE(PCLK_UPHY1_TCPD_G, "pclk_uphy1_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 9, GFLAGS), | ||
1286 | |||
1287 | GATE(PCLK_GRF, "pclk_grf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 1, GFLAGS), | ||
1288 | GATE(PCLK_INTR_ARB, "pclk_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 2, GFLAGS), | ||
1289 | GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 3, GFLAGS), | ||
1290 | GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 4, GFLAGS), | ||
1291 | GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 5, GFLAGS), | ||
1292 | GATE(PCLK_TIMER0, "pclk_timer0", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 6, GFLAGS), | ||
1293 | GATE(PCLK_TIMER1, "pclk_timer1", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 7, GFLAGS), | ||
1294 | GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS), | ||
1295 | GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS), | ||
1296 | |||
1297 | GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS), | ||
1298 | GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS), | ||
1299 | |||
1300 | GATE(SCLK_MIPIDPHY_CFG, "clk_mipidphy_cfg", "xin24m", 0, RK3399_CLKGATE_CON(11), 15, GFLAGS), | ||
1301 | GATE(SCLK_DPHY_TX0_CFG, "clk_dphy_tx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 1, GFLAGS), | ||
1302 | GATE(SCLK_DPHY_TX1RX1_CFG, "clk_dphy_tx1rx1_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 2, GFLAGS), | ||
1303 | GATE(SCLK_DPHY_RX0_CFG, "clk_dphy_rx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 3, GFLAGS), | ||
1304 | |||
1305 | /* testout */ | ||
1306 | MUX(0, "clk_test_pre", mux_pll_src_cpll_gpll_p, CLK_SET_RATE_PARENT, | ||
1307 | RK3399_CLKSEL_CON(58), 7, 1, MFLAGS), | ||
1308 | COMPOSITE_FRAC(0, "clk_test_frac", "clk_test_pre", CLK_SET_RATE_PARENT, | ||
1309 | RK3399_CLKSEL_CON(105), 0, | ||
1310 | RK3399_CLKGATE_CON(13), 9, GFLAGS), | ||
1311 | |||
1312 | DIV(0, "clk_test_24m", "xin24m", 0, | ||
1313 | RK3399_CLKSEL_CON(57), 6, 10, DFLAGS), | ||
1314 | |||
1315 | /* spi */ | ||
1316 | COMPOSITE(SCLK_SPI0, "clk_spi0", mux_pll_src_cpll_gpll_p, 0, | ||
1317 | RK3399_CLKSEL_CON(59), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
1318 | RK3399_CLKGATE_CON(9), 12, GFLAGS), | ||
1319 | |||
1320 | COMPOSITE(SCLK_SPI1, "clk_spi1", mux_pll_src_cpll_gpll_p, 0, | ||
1321 | RK3399_CLKSEL_CON(59), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
1322 | RK3399_CLKGATE_CON(9), 13, GFLAGS), | ||
1323 | |||
1324 | COMPOSITE(SCLK_SPI2, "clk_spi2", mux_pll_src_cpll_gpll_p, 0, | ||
1325 | RK3399_CLKSEL_CON(60), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
1326 | RK3399_CLKGATE_CON(9), 14, GFLAGS), | ||
1327 | |||
1328 | COMPOSITE(SCLK_SPI4, "clk_spi4", mux_pll_src_cpll_gpll_p, 0, | ||
1329 | RK3399_CLKSEL_CON(60), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
1330 | RK3399_CLKGATE_CON(9), 15, GFLAGS), | ||
1331 | |||
1332 | COMPOSITE(SCLK_SPI5, "clk_spi5", mux_pll_src_cpll_gpll_p, 0, | ||
1333 | RK3399_CLKSEL_CON(58), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
1334 | RK3399_CLKGATE_CON(13), 13, GFLAGS), | ||
1335 | |||
1336 | /* i2c */ | ||
1337 | COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_pll_src_cpll_gpll_p, 0, | ||
1338 | RK3399_CLKSEL_CON(61), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
1339 | RK3399_CLKGATE_CON(10), 0, GFLAGS), | ||
1340 | |||
1341 | COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_pll_src_cpll_gpll_p, 0, | ||
1342 | RK3399_CLKSEL_CON(62), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
1343 | RK3399_CLKGATE_CON(10), 2, GFLAGS), | ||
1344 | |||
1345 | COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_pll_src_cpll_gpll_p, 0, | ||
1346 | RK3399_CLKSEL_CON(63), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
1347 | RK3399_CLKGATE_CON(10), 4, GFLAGS), | ||
1348 | |||
1349 | COMPOSITE(SCLK_I2C5, "clk_i2c5", mux_pll_src_cpll_gpll_p, 0, | ||
1350 | RK3399_CLKSEL_CON(61), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
1351 | RK3399_CLKGATE_CON(10), 1, GFLAGS), | ||
1352 | |||
1353 | COMPOSITE(SCLK_I2C6, "clk_i2c6", mux_pll_src_cpll_gpll_p, 0, | ||
1354 | RK3399_CLKSEL_CON(62), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
1355 | RK3399_CLKGATE_CON(10), 3, GFLAGS), | ||
1356 | |||
1357 | COMPOSITE(SCLK_I2C7, "clk_i2c7", mux_pll_src_cpll_gpll_p, 0, | ||
1358 | RK3399_CLKSEL_CON(63), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
1359 | RK3399_CLKGATE_CON(10), 5, GFLAGS), | ||
1360 | |||
1361 | /* timer */ | ||
1362 | GATE(SCLK_TIMER00, "clk_timer00", "xin24m", 0, RK3399_CLKGATE_CON(26), 0, GFLAGS), | ||
1363 | GATE(SCLK_TIMER01, "clk_timer01", "xin24m", 0, RK3399_CLKGATE_CON(26), 1, GFLAGS), | ||
1364 | GATE(SCLK_TIMER02, "clk_timer02", "xin24m", 0, RK3399_CLKGATE_CON(26), 2, GFLAGS), | ||
1365 | GATE(SCLK_TIMER03, "clk_timer03", "xin24m", 0, RK3399_CLKGATE_CON(26), 3, GFLAGS), | ||
1366 | GATE(SCLK_TIMER04, "clk_timer04", "xin24m", 0, RK3399_CLKGATE_CON(26), 4, GFLAGS), | ||
1367 | GATE(SCLK_TIMER05, "clk_timer05", "xin24m", 0, RK3399_CLKGATE_CON(26), 5, GFLAGS), | ||
1368 | GATE(SCLK_TIMER06, "clk_timer06", "xin24m", 0, RK3399_CLKGATE_CON(26), 6, GFLAGS), | ||
1369 | GATE(SCLK_TIMER07, "clk_timer07", "xin24m", 0, RK3399_CLKGATE_CON(26), 7, GFLAGS), | ||
1370 | GATE(SCLK_TIMER08, "clk_timer08", "xin24m", 0, RK3399_CLKGATE_CON(26), 8, GFLAGS), | ||
1371 | GATE(SCLK_TIMER09, "clk_timer09", "xin24m", 0, RK3399_CLKGATE_CON(26), 9, GFLAGS), | ||
1372 | GATE(SCLK_TIMER10, "clk_timer10", "xin24m", 0, RK3399_CLKGATE_CON(26), 10, GFLAGS), | ||
1373 | GATE(SCLK_TIMER11, "clk_timer11", "xin24m", 0, RK3399_CLKGATE_CON(26), 11, GFLAGS), | ||
1374 | |||
1375 | /* clk_test */ | ||
1376 | /* clk_test_pre is controlled by CRU_MISC_CON[3] */ | ||
1377 | COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED, | ||
1378 | RK3368_CLKSEL_CON(58), 0, 5, DFLAGS, | ||
1379 | RK3368_CLKGATE_CON(13), 11, GFLAGS), | ||
1380 | }; | ||
1381 | |||
1382 | static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { | ||
1383 | /* | ||
1384 | * PMU CRU Clock-Architecture | ||
1385 | */ | ||
1386 | |||
1387 | GATE(0, "fclk_cm0s_pmu_ppll_src", "ppll", 0, | ||
1388 | RK3399_PMU_CLKGATE_CON(0), 1, GFLAGS), | ||
1389 | |||
1390 | COMPOSITE_NOGATE(FCLK_CM0S_SRC_PMU, "fclk_cm0s_src_pmu", mux_fclk_cm0s_pmu_ppll_p, 0, | ||
1391 | RK3399_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS), | ||
1392 | |||
1393 | COMPOSITE(SCLK_SPI3_PMU, "clk_spi3_pmu", mux_24m_ppll_p, 0, | ||
1394 | RK3399_PMU_CLKSEL_CON(1), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
1395 | RK3399_PMU_CLKGATE_CON(0), 2, GFLAGS), | ||
1396 | |||
1397 | COMPOSITE(0, "clk_wifi_div", mux_ppll_24m_p, CLK_IGNORE_UNUSED, | ||
1398 | RK3399_PMU_CLKSEL_CON(1), 13, 1, MFLAGS, 8, 5, DFLAGS, | ||
1399 | RK3399_PMU_CLKGATE_CON(0), 8, GFLAGS), | ||
1400 | |||
1401 | COMPOSITE_FRACMUX_NOGATE(0, "clk_wifi_frac", "clk_wifi_div", CLK_SET_RATE_PARENT, | ||
1402 | RK3399_PMU_CLKSEL_CON(7), 0, | ||
1403 | &rk3399_pmuclk_wifi_fracmux), | ||
1404 | |||
1405 | MUX(0, "clk_timer_src_pmu", mux_pll_p, CLK_IGNORE_UNUSED, | ||
1406 | RK3399_PMU_CLKSEL_CON(1), 15, 1, MFLAGS), | ||
1407 | |||
1408 | COMPOSITE_NOMUX(SCLK_I2C0_PMU, "clk_i2c0_pmu", "ppll", 0, | ||
1409 | RK3399_PMU_CLKSEL_CON(2), 0, 7, DFLAGS, | ||
1410 | RK3399_PMU_CLKGATE_CON(0), 9, GFLAGS), | ||
1411 | |||
1412 | COMPOSITE_NOMUX(SCLK_I2C4_PMU, "clk_i2c4_pmu", "ppll", 0, | ||
1413 | RK3399_PMU_CLKSEL_CON(3), 0, 7, DFLAGS, | ||
1414 | RK3399_PMU_CLKGATE_CON(0), 10, GFLAGS), | ||
1415 | |||
1416 | COMPOSITE_NOMUX(SCLK_I2C8_PMU, "clk_i2c8_pmu", "ppll", 0, | ||
1417 | RK3399_PMU_CLKSEL_CON(2), 8, 7, DFLAGS, | ||
1418 | RK3399_PMU_CLKGATE_CON(0), 11, GFLAGS), | ||
1419 | |||
1420 | DIV(0, "clk_32k_suspend_pmu", "xin24m", CLK_IGNORE_UNUSED, | ||
1421 | RK3399_PMU_CLKSEL_CON(4), 0, 10, DFLAGS), | ||
1422 | MUX(0, "clk_testout_2io", mux_clk_testout2_2io_p, CLK_IGNORE_UNUSED, | ||
1423 | RK3399_PMU_CLKSEL_CON(4), 15, 1, MFLAGS), | ||
1424 | |||
1425 | COMPOSITE(0, "clk_uart4_div", mux_24m_ppll_p, 0, | ||
1426 | RK3399_PMU_CLKSEL_CON(5), 10, 1, MFLAGS, 0, 7, DFLAGS, | ||
1427 | RK3399_PMU_CLKGATE_CON(0), 5, GFLAGS), | ||
1428 | |||
1429 | COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_div", CLK_SET_RATE_PARENT, | ||
1430 | RK3399_PMU_CLKSEL_CON(6), 0, | ||
1431 | RK3399_PMU_CLKGATE_CON(0), 6, GFLAGS, | ||
1432 | &rk3399_uart4_pmu_fracmux), | ||
1433 | |||
1434 | DIV(PCLK_SRC_PMU, "pclk_pmu_src", "ppll", CLK_IGNORE_UNUSED, | ||
1435 | RK3399_PMU_CLKSEL_CON(0), 0, 5, DFLAGS), | ||
1436 | |||
1437 | /* pmu clock gates */ | ||
1438 | GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 3, GFLAGS), | ||
1439 | GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 4, GFLAGS), | ||
1440 | |||
1441 | GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 7, GFLAGS), | ||
1442 | |||
1443 | GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 0, GFLAGS), | ||
1444 | GATE(PCLK_PMUGRF_PMU, "pclk_pmugrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 1, GFLAGS), | ||
1445 | GATE(PCLK_INTMEM1_PMU, "pclk_intmem1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 2, GFLAGS), | ||
1446 | GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 3, GFLAGS), | ||
1447 | GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 4, GFLAGS), | ||
1448 | GATE(PCLK_SGRF_PMU, "pclk_sgrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 5, GFLAGS), | ||
1449 | GATE(PCLK_NOC_PMU, "pclk_noc_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 6, GFLAGS), | ||
1450 | GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 7, GFLAGS), | ||
1451 | GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 8, GFLAGS), | ||
1452 | GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 9, GFLAGS), | ||
1453 | GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 10, GFLAGS), | ||
1454 | GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 11, GFLAGS), | ||
1455 | GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 12, GFLAGS), | ||
1456 | GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 13, GFLAGS), | ||
1457 | GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS), | ||
1458 | GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS), | ||
1459 | |||
1460 | GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS), | ||
1461 | GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS), | ||
1462 | GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS), | ||
1463 | GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS), | ||
1464 | GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS), | ||
1465 | }; | ||
1466 | |||
1467 | static const char *const rk3399_cru_critical_clocks[] __initconst = { | ||
1468 | "aclk_cci_pre", | ||
1469 | "pclk_perilp0", | ||
1470 | "pclk_perilp0", | ||
1471 | "hclk_perilp0", | ||
1472 | "hclk_perilp0_noc", | ||
1473 | "pclk_perilp1", | ||
1474 | "pclk_perilp1_noc", | ||
1475 | "pclk_perihp", | ||
1476 | "pclk_perihp_noc", | ||
1477 | "hclk_perihp", | ||
1478 | "aclk_perihp", | ||
1479 | "aclk_perihp_noc", | ||
1480 | "aclk_perilp0", | ||
1481 | "aclk_perilp0_noc", | ||
1482 | "hclk_perilp1", | ||
1483 | "hclk_perilp1_noc", | ||
1484 | "aclk_dmac0_perilp", | ||
1485 | "gpll_hclk_perilp1_src", | ||
1486 | "gpll_aclk_perilp0_src", | ||
1487 | "gpll_aclk_perihp_src", | ||
1488 | }; | ||
1489 | |||
1490 | static const char *const rk3399_pmucru_critical_clocks[] __initconst = { | ||
1491 | "ppll", | ||
1492 | "pclk_pmu_src", | ||
1493 | "fclk_cm0s_src_pmu", | ||
1494 | "clk_timer_src_pmu", | ||
1495 | }; | ||
1496 | |||
1497 | static void __init rk3399_clk_init(struct device_node *np) | ||
1498 | { | ||
1499 | struct rockchip_clk_provider *ctx; | ||
1500 | void __iomem *reg_base; | ||
1501 | |||
1502 | reg_base = of_iomap(np, 0); | ||
1503 | if (!reg_base) { | ||
1504 | pr_err("%s: could not map cru region\n", __func__); | ||
1505 | return; | ||
1506 | } | ||
1507 | |||
1508 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | ||
1509 | if (IS_ERR(ctx)) { | ||
1510 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
1511 | return; | ||
1512 | } | ||
1513 | |||
1514 | rockchip_clk_register_plls(ctx, rk3399_pll_clks, | ||
1515 | ARRAY_SIZE(rk3399_pll_clks), -1); | ||
1516 | |||
1517 | rockchip_clk_register_branches(ctx, rk3399_clk_branches, | ||
1518 | ARRAY_SIZE(rk3399_clk_branches)); | ||
1519 | |||
1520 | rockchip_clk_protect_critical(rk3399_cru_critical_clocks, | ||
1521 | ARRAY_SIZE(rk3399_cru_critical_clocks)); | ||
1522 | |||
1523 | rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl", | ||
1524 | mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), | ||
1525 | &rk3399_cpuclkl_data, rk3399_cpuclkl_rates, | ||
1526 | ARRAY_SIZE(rk3399_cpuclkl_rates)); | ||
1527 | |||
1528 | rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb", | ||
1529 | mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), | ||
1530 | &rk3399_cpuclkb_data, rk3399_cpuclkb_rates, | ||
1531 | ARRAY_SIZE(rk3399_cpuclkb_rates)); | ||
1532 | |||
1533 | rockchip_register_softrst(np, 21, reg_base + RK3399_SOFTRST_CON(0), | ||
1534 | ROCKCHIP_SOFTRST_HIWORD_MASK); | ||
1535 | |||
1536 | rockchip_register_restart_notifier(ctx, RK3399_GLB_SRST_FST, NULL); | ||
1537 | |||
1538 | rockchip_clk_of_add_provider(np, ctx); | ||
1539 | } | ||
1540 | CLK_OF_DECLARE(rk3399_cru, "rockchip,rk3399-cru", rk3399_clk_init); | ||
1541 | |||
1542 | static void __init rk3399_pmu_clk_init(struct device_node *np) | ||
1543 | { | ||
1544 | struct rockchip_clk_provider *ctx; | ||
1545 | void __iomem *reg_base; | ||
1546 | |||
1547 | reg_base = of_iomap(np, 0); | ||
1548 | if (!reg_base) { | ||
1549 | pr_err("%s: could not map cru pmu region\n", __func__); | ||
1550 | return; | ||
1551 | } | ||
1552 | |||
1553 | ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS); | ||
1554 | if (IS_ERR(ctx)) { | ||
1555 | pr_err("%s: rockchip pmu clk init failed\n", __func__); | ||
1556 | return; | ||
1557 | } | ||
1558 | |||
1559 | rockchip_clk_register_plls(ctx, rk3399_pmu_pll_clks, | ||
1560 | ARRAY_SIZE(rk3399_pmu_pll_clks), -1); | ||
1561 | |||
1562 | rockchip_clk_register_branches(ctx, rk3399_clk_pmu_branches, | ||
1563 | ARRAY_SIZE(rk3399_clk_pmu_branches)); | ||
1564 | |||
1565 | rockchip_clk_protect_critical(rk3399_pmucru_critical_clocks, | ||
1566 | ARRAY_SIZE(rk3399_pmucru_critical_clocks)); | ||
1567 | |||
1568 | rockchip_register_softrst(np, 2, reg_base + RK3399_PMU_SOFTRST_CON(0), | ||
1569 | ROCKCHIP_SOFTRST_HIWORD_MASK); | ||
1570 | |||
1571 | rockchip_clk_of_add_provider(np, ctx); | ||
1572 | } | ||
1573 | CLK_OF_DECLARE(rk3399_cru_pmu, "rockchip,rk3399-pmucru", rk3399_pmu_clk_init); | ||
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index ec06350c78c4..7ffd134995f2 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c | |||
@@ -2,6 +2,9 @@ | |||
2 | * Copyright (c) 2014 MundoReader S.L. | 2 | * Copyright (c) 2014 MundoReader S.L. |
3 | * Author: Heiko Stuebner <heiko@sntech.de> | 3 | * Author: Heiko Stuebner <heiko@sntech.de> |
4 | * | 4 | * |
5 | * Copyright (c) 2016 Rockchip Electronics Co. Ltd. | ||
6 | * Author: Xing Zheng <zhengxing@rock-chips.com> | ||
7 | * | ||
5 | * based on | 8 | * based on |
6 | * | 9 | * |
7 | * samsung/clk.c | 10 | * samsung/clk.c |
@@ -39,7 +42,8 @@ | |||
39 | * sometimes without one of those components. | 42 | * sometimes without one of those components. |
40 | */ | 43 | */ |
41 | static struct clk *rockchip_clk_register_branch(const char *name, | 44 | static struct clk *rockchip_clk_register_branch(const char *name, |
42 | const char *const *parent_names, u8 num_parents, void __iomem *base, | 45 | const char *const *parent_names, u8 num_parents, |
46 | void __iomem *base, | ||
43 | int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, | 47 | int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, |
44 | u8 div_shift, u8 div_width, u8 div_flags, | 48 | u8 div_shift, u8 div_width, u8 div_flags, |
45 | struct clk_div_table *div_table, int gate_offset, | 49 | struct clk_div_table *div_table, int gate_offset, |
@@ -136,9 +140,11 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, | |||
136 | pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n", | 140 | pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n", |
137 | __func__, event, ndata->old_rate, ndata->new_rate); | 141 | __func__, event, ndata->old_rate, ndata->new_rate); |
138 | if (event == PRE_RATE_CHANGE) { | 142 | if (event == PRE_RATE_CHANGE) { |
139 | frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw); | 143 | frac->rate_change_idx = |
144 | frac->mux_ops->get_parent(&frac_mux->hw); | ||
140 | if (frac->rate_change_idx != frac->mux_frac_idx) { | 145 | if (frac->rate_change_idx != frac->mux_frac_idx) { |
141 | frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx); | 146 | frac->mux_ops->set_parent(&frac_mux->hw, |
147 | frac->mux_frac_idx); | ||
142 | frac->rate_change_remuxed = 1; | 148 | frac->rate_change_remuxed = 1; |
143 | } | 149 | } |
144 | } else if (event == POST_RATE_CHANGE) { | 150 | } else if (event == POST_RATE_CHANGE) { |
@@ -149,7 +155,8 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, | |||
149 | * reaches the mux itself. | 155 | * reaches the mux itself. |
150 | */ | 156 | */ |
151 | if (frac->rate_change_remuxed) { | 157 | if (frac->rate_change_remuxed) { |
152 | frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx); | 158 | frac->mux_ops->set_parent(&frac_mux->hw, |
159 | frac->rate_change_idx); | ||
153 | frac->rate_change_remuxed = 0; | 160 | frac->rate_change_remuxed = 0; |
154 | } | 161 | } |
155 | } | 162 | } |
@@ -157,7 +164,8 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, | |||
157 | return notifier_from_errno(ret); | 164 | return notifier_from_errno(ret); |
158 | } | 165 | } |
159 | 166 | ||
160 | static struct clk *rockchip_clk_register_frac_branch(const char *name, | 167 | static struct clk *rockchip_clk_register_frac_branch( |
168 | struct rockchip_clk_provider *ctx, const char *name, | ||
161 | const char *const *parent_names, u8 num_parents, | 169 | const char *const *parent_names, u8 num_parents, |
162 | void __iomem *base, int muxdiv_offset, u8 div_flags, | 170 | void __iomem *base, int muxdiv_offset, u8 div_flags, |
163 | int gate_offset, u8 gate_shift, u8 gate_flags, | 171 | int gate_offset, u8 gate_shift, u8 gate_flags, |
@@ -250,7 +258,7 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name, | |||
250 | if (IS_ERR(mux_clk)) | 258 | if (IS_ERR(mux_clk)) |
251 | return clk; | 259 | return clk; |
252 | 260 | ||
253 | rockchip_clk_add_lookup(mux_clk, child->id); | 261 | rockchip_clk_add_lookup(ctx, mux_clk, child->id); |
254 | 262 | ||
255 | /* notifier on the fraction divider to catch rate changes */ | 263 | /* notifier on the fraction divider to catch rate changes */ |
256 | if (frac->mux_frac_idx >= 0) { | 264 | if (frac->mux_frac_idx >= 0) { |
@@ -314,66 +322,82 @@ static struct clk *rockchip_clk_register_factor_branch(const char *name, | |||
314 | return clk; | 322 | return clk; |
315 | } | 323 | } |
316 | 324 | ||
317 | static DEFINE_SPINLOCK(clk_lock); | 325 | struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, |
318 | static struct clk **clk_table; | 326 | void __iomem *base, unsigned long nr_clks) |
319 | static void __iomem *reg_base; | ||
320 | static struct clk_onecell_data clk_data; | ||
321 | static struct device_node *cru_node; | ||
322 | static struct regmap *grf; | ||
323 | |||
324 | void __init rockchip_clk_init(struct device_node *np, void __iomem *base, | ||
325 | unsigned long nr_clks) | ||
326 | { | 327 | { |
327 | reg_base = base; | 328 | struct rockchip_clk_provider *ctx; |
328 | cru_node = np; | 329 | struct clk **clk_table; |
329 | grf = ERR_PTR(-EPROBE_DEFER); | 330 | int i; |
331 | |||
332 | ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL); | ||
333 | if (!ctx) | ||
334 | return ERR_PTR(-ENOMEM); | ||
330 | 335 | ||
331 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); | 336 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); |
332 | if (!clk_table) | 337 | if (!clk_table) |
333 | pr_err("%s: could not allocate clock lookup table\n", __func__); | 338 | goto err_free; |
334 | 339 | ||
335 | clk_data.clks = clk_table; | 340 | for (i = 0; i < nr_clks; ++i) |
336 | clk_data.clk_num = nr_clks; | 341 | clk_table[i] = ERR_PTR(-ENOENT); |
337 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 342 | |
343 | ctx->reg_base = base; | ||
344 | ctx->clk_data.clks = clk_table; | ||
345 | ctx->clk_data.clk_num = nr_clks; | ||
346 | ctx->cru_node = np; | ||
347 | ctx->grf = ERR_PTR(-EPROBE_DEFER); | ||
348 | spin_lock_init(&ctx->lock); | ||
349 | |||
350 | ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, | ||
351 | "rockchip,grf"); | ||
352 | |||
353 | return ctx; | ||
354 | |||
355 | err_free: | ||
356 | kfree(ctx); | ||
357 | return ERR_PTR(-ENOMEM); | ||
338 | } | 358 | } |
339 | 359 | ||
340 | struct regmap *rockchip_clk_get_grf(void) | 360 | void __init rockchip_clk_of_add_provider(struct device_node *np, |
361 | struct rockchip_clk_provider *ctx) | ||
341 | { | 362 | { |
342 | if (IS_ERR(grf)) | 363 | if (of_clk_add_provider(np, of_clk_src_onecell_get, |
343 | grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf"); | 364 | &ctx->clk_data)) |
344 | return grf; | 365 | pr_err("%s: could not register clk provider\n", __func__); |
345 | } | 366 | } |
346 | 367 | ||
347 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id) | 368 | void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, |
369 | struct clk *clk, unsigned int id) | ||
348 | { | 370 | { |
349 | if (clk_table && id) | 371 | if (ctx->clk_data.clks && id) |
350 | clk_table[id] = clk; | 372 | ctx->clk_data.clks[id] = clk; |
351 | } | 373 | } |
352 | 374 | ||
353 | void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, | 375 | void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, |
376 | struct rockchip_pll_clock *list, | ||
354 | unsigned int nr_pll, int grf_lock_offset) | 377 | unsigned int nr_pll, int grf_lock_offset) |
355 | { | 378 | { |
356 | struct clk *clk; | 379 | struct clk *clk; |
357 | int idx; | 380 | int idx; |
358 | 381 | ||
359 | for (idx = 0; idx < nr_pll; idx++, list++) { | 382 | for (idx = 0; idx < nr_pll; idx++, list++) { |
360 | clk = rockchip_clk_register_pll(list->type, list->name, | 383 | clk = rockchip_clk_register_pll(ctx, list->type, list->name, |
361 | list->parent_names, list->num_parents, | 384 | list->parent_names, list->num_parents, |
362 | reg_base, list->con_offset, grf_lock_offset, | 385 | list->con_offset, grf_lock_offset, |
363 | list->lock_shift, list->mode_offset, | 386 | list->lock_shift, list->mode_offset, |
364 | list->mode_shift, list->rate_table, | 387 | list->mode_shift, list->rate_table, |
365 | list->pll_flags, &clk_lock); | 388 | list->pll_flags); |
366 | if (IS_ERR(clk)) { | 389 | if (IS_ERR(clk)) { |
367 | pr_err("%s: failed to register clock %s\n", __func__, | 390 | pr_err("%s: failed to register clock %s\n", __func__, |
368 | list->name); | 391 | list->name); |
369 | continue; | 392 | continue; |
370 | } | 393 | } |
371 | 394 | ||
372 | rockchip_clk_add_lookup(clk, list->id); | 395 | rockchip_clk_add_lookup(ctx, clk, list->id); |
373 | } | 396 | } |
374 | } | 397 | } |
375 | 398 | ||
376 | void __init rockchip_clk_register_branches( | 399 | void __init rockchip_clk_register_branches( |
400 | struct rockchip_clk_provider *ctx, | ||
377 | struct rockchip_clk_branch *list, | 401 | struct rockchip_clk_branch *list, |
378 | unsigned int nr_clk) | 402 | unsigned int nr_clk) |
379 | { | 403 | { |
@@ -389,56 +413,59 @@ void __init rockchip_clk_register_branches( | |||
389 | case branch_mux: | 413 | case branch_mux: |
390 | clk = clk_register_mux(NULL, list->name, | 414 | clk = clk_register_mux(NULL, list->name, |
391 | list->parent_names, list->num_parents, | 415 | list->parent_names, list->num_parents, |
392 | flags, reg_base + list->muxdiv_offset, | 416 | flags, ctx->reg_base + list->muxdiv_offset, |
393 | list->mux_shift, list->mux_width, | 417 | list->mux_shift, list->mux_width, |
394 | list->mux_flags, &clk_lock); | 418 | list->mux_flags, &ctx->lock); |
395 | break; | 419 | break; |
396 | case branch_divider: | 420 | case branch_divider: |
397 | if (list->div_table) | 421 | if (list->div_table) |
398 | clk = clk_register_divider_table(NULL, | 422 | clk = clk_register_divider_table(NULL, |
399 | list->name, list->parent_names[0], | 423 | list->name, list->parent_names[0], |
400 | flags, reg_base + list->muxdiv_offset, | 424 | flags, |
425 | ctx->reg_base + list->muxdiv_offset, | ||
401 | list->div_shift, list->div_width, | 426 | list->div_shift, list->div_width, |
402 | list->div_flags, list->div_table, | 427 | list->div_flags, list->div_table, |
403 | &clk_lock); | 428 | &ctx->lock); |
404 | else | 429 | else |
405 | clk = clk_register_divider(NULL, list->name, | 430 | clk = clk_register_divider(NULL, list->name, |
406 | list->parent_names[0], flags, | 431 | list->parent_names[0], flags, |
407 | reg_base + list->muxdiv_offset, | 432 | ctx->reg_base + list->muxdiv_offset, |
408 | list->div_shift, list->div_width, | 433 | list->div_shift, list->div_width, |
409 | list->div_flags, &clk_lock); | 434 | list->div_flags, &ctx->lock); |
410 | break; | 435 | break; |
411 | case branch_fraction_divider: | 436 | case branch_fraction_divider: |
412 | clk = rockchip_clk_register_frac_branch(list->name, | 437 | clk = rockchip_clk_register_frac_branch(ctx, list->name, |
413 | list->parent_names, list->num_parents, | 438 | list->parent_names, list->num_parents, |
414 | reg_base, list->muxdiv_offset, list->div_flags, | 439 | ctx->reg_base, list->muxdiv_offset, |
440 | list->div_flags, | ||
415 | list->gate_offset, list->gate_shift, | 441 | list->gate_offset, list->gate_shift, |
416 | list->gate_flags, flags, list->child, | 442 | list->gate_flags, flags, list->child, |
417 | &clk_lock); | 443 | &ctx->lock); |
418 | break; | 444 | break; |
419 | case branch_gate: | 445 | case branch_gate: |
420 | flags |= CLK_SET_RATE_PARENT; | 446 | flags |= CLK_SET_RATE_PARENT; |
421 | 447 | ||
422 | clk = clk_register_gate(NULL, list->name, | 448 | clk = clk_register_gate(NULL, list->name, |
423 | list->parent_names[0], flags, | 449 | list->parent_names[0], flags, |
424 | reg_base + list->gate_offset, | 450 | ctx->reg_base + list->gate_offset, |
425 | list->gate_shift, list->gate_flags, &clk_lock); | 451 | list->gate_shift, list->gate_flags, &ctx->lock); |
426 | break; | 452 | break; |
427 | case branch_composite: | 453 | case branch_composite: |
428 | clk = rockchip_clk_register_branch(list->name, | 454 | clk = rockchip_clk_register_branch(list->name, |
429 | list->parent_names, list->num_parents, | 455 | list->parent_names, list->num_parents, |
430 | reg_base, list->muxdiv_offset, list->mux_shift, | 456 | ctx->reg_base, list->muxdiv_offset, |
457 | list->mux_shift, | ||
431 | list->mux_width, list->mux_flags, | 458 | list->mux_width, list->mux_flags, |
432 | list->div_shift, list->div_width, | 459 | list->div_shift, list->div_width, |
433 | list->div_flags, list->div_table, | 460 | list->div_flags, list->div_table, |
434 | list->gate_offset, list->gate_shift, | 461 | list->gate_offset, list->gate_shift, |
435 | list->gate_flags, flags, &clk_lock); | 462 | list->gate_flags, flags, &ctx->lock); |
436 | break; | 463 | break; |
437 | case branch_mmc: | 464 | case branch_mmc: |
438 | clk = rockchip_clk_register_mmc( | 465 | clk = rockchip_clk_register_mmc( |
439 | list->name, | 466 | list->name, |
440 | list->parent_names, list->num_parents, | 467 | list->parent_names, list->num_parents, |
441 | reg_base + list->muxdiv_offset, | 468 | ctx->reg_base + list->muxdiv_offset, |
442 | list->div_shift | 469 | list->div_shift |
443 | ); | 470 | ); |
444 | break; | 471 | break; |
@@ -446,16 +473,16 @@ void __init rockchip_clk_register_branches( | |||
446 | clk = rockchip_clk_register_inverter( | 473 | clk = rockchip_clk_register_inverter( |
447 | list->name, list->parent_names, | 474 | list->name, list->parent_names, |
448 | list->num_parents, | 475 | list->num_parents, |
449 | reg_base + list->muxdiv_offset, | 476 | ctx->reg_base + list->muxdiv_offset, |
450 | list->div_shift, list->div_flags, &clk_lock); | 477 | list->div_shift, list->div_flags, &ctx->lock); |
451 | break; | 478 | break; |
452 | case branch_factor: | 479 | case branch_factor: |
453 | clk = rockchip_clk_register_factor_branch( | 480 | clk = rockchip_clk_register_factor_branch( |
454 | list->name, list->parent_names, | 481 | list->name, list->parent_names, |
455 | list->num_parents, reg_base, | 482 | list->num_parents, ctx->reg_base, |
456 | list->div_shift, list->div_width, | 483 | list->div_shift, list->div_width, |
457 | list->gate_offset, list->gate_shift, | 484 | list->gate_offset, list->gate_shift, |
458 | list->gate_flags, flags, &clk_lock); | 485 | list->gate_flags, flags, &ctx->lock); |
459 | break; | 486 | break; |
460 | } | 487 | } |
461 | 488 | ||
@@ -472,11 +499,12 @@ void __init rockchip_clk_register_branches( | |||
472 | continue; | 499 | continue; |
473 | } | 500 | } |
474 | 501 | ||
475 | rockchip_clk_add_lookup(clk, list->id); | 502 | rockchip_clk_add_lookup(ctx, clk, list->id); |
476 | } | 503 | } |
477 | } | 504 | } |
478 | 505 | ||
479 | void __init rockchip_clk_register_armclk(unsigned int lookup_id, | 506 | void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, |
507 | unsigned int lookup_id, | ||
480 | const char *name, const char *const *parent_names, | 508 | const char *name, const char *const *parent_names, |
481 | u8 num_parents, | 509 | u8 num_parents, |
482 | const struct rockchip_cpuclk_reg_data *reg_data, | 510 | const struct rockchip_cpuclk_reg_data *reg_data, |
@@ -486,15 +514,15 @@ void __init rockchip_clk_register_armclk(unsigned int lookup_id, | |||
486 | struct clk *clk; | 514 | struct clk *clk; |
487 | 515 | ||
488 | clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, | 516 | clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, |
489 | reg_data, rates, nrates, reg_base, | 517 | reg_data, rates, nrates, |
490 | &clk_lock); | 518 | ctx->reg_base, &ctx->lock); |
491 | if (IS_ERR(clk)) { | 519 | if (IS_ERR(clk)) { |
492 | pr_err("%s: failed to register clock %s: %ld\n", | 520 | pr_err("%s: failed to register clock %s: %ld\n", |
493 | __func__, name, PTR_ERR(clk)); | 521 | __func__, name, PTR_ERR(clk)); |
494 | return; | 522 | return; |
495 | } | 523 | } |
496 | 524 | ||
497 | rockchip_clk_add_lookup(clk, lookup_id); | 525 | rockchip_clk_add_lookup(ctx, clk, lookup_id); |
498 | } | 526 | } |
499 | 527 | ||
500 | void __init rockchip_clk_protect_critical(const char *const clocks[], | 528 | void __init rockchip_clk_protect_critical(const char *const clocks[], |
@@ -511,6 +539,7 @@ void __init rockchip_clk_protect_critical(const char *const clocks[], | |||
511 | } | 539 | } |
512 | } | 540 | } |
513 | 541 | ||
542 | static void __iomem *rst_base; | ||
514 | static unsigned int reg_restart; | 543 | static unsigned int reg_restart; |
515 | static void (*cb_restart)(void); | 544 | static void (*cb_restart)(void); |
516 | static int rockchip_restart_notify(struct notifier_block *this, | 545 | static int rockchip_restart_notify(struct notifier_block *this, |
@@ -519,7 +548,7 @@ static int rockchip_restart_notify(struct notifier_block *this, | |||
519 | if (cb_restart) | 548 | if (cb_restart) |
520 | cb_restart(); | 549 | cb_restart(); |
521 | 550 | ||
522 | writel(0xfdb9, reg_base + reg_restart); | 551 | writel(0xfdb9, rst_base + reg_restart); |
523 | return NOTIFY_DONE; | 552 | return NOTIFY_DONE; |
524 | } | 553 | } |
525 | 554 | ||
@@ -528,10 +557,14 @@ static struct notifier_block rockchip_restart_handler = { | |||
528 | .priority = 128, | 557 | .priority = 128, |
529 | }; | 558 | }; |
530 | 559 | ||
531 | void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)) | 560 | void __init |
561 | rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, | ||
562 | unsigned int reg, | ||
563 | void (*cb)(void)) | ||
532 | { | 564 | { |
533 | int ret; | 565 | int ret; |
534 | 566 | ||
567 | rst_base = ctx->reg_base; | ||
535 | reg_restart = reg; | 568 | reg_restart = reg; |
536 | cb_restart = cb; | 569 | cb_restart = cb; |
537 | ret = register_restart_handler(&rockchip_restart_handler); | 570 | ret = register_restart_handler(&rockchip_restart_handler); |
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 39c198bbcbee..2194ffa8c9fd 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h | |||
@@ -27,13 +27,13 @@ | |||
27 | #define CLK_ROCKCHIP_CLK_H | 27 | #define CLK_ROCKCHIP_CLK_H |
28 | 28 | ||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/clk-provider.h> | ||
30 | 31 | ||
31 | struct clk; | 32 | struct clk; |
32 | 33 | ||
33 | #define HIWORD_UPDATE(val, mask, shift) \ | 34 | #define HIWORD_UPDATE(val, mask, shift) \ |
34 | ((val) << (shift) | (mask) << ((shift) + 16)) | 35 | ((val) << (shift) | (mask) << ((shift) + 16)) |
35 | 36 | ||
36 | /* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */ | ||
37 | #define RK2928_PLL_CON(x) ((x) * 0x4) | 37 | #define RK2928_PLL_CON(x) ((x) * 0x4) |
38 | #define RK2928_MODE_CON 0x40 | 38 | #define RK2928_MODE_CON 0x40 |
39 | #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) | 39 | #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) |
@@ -92,9 +92,30 @@ struct clk; | |||
92 | #define RK3368_EMMC_CON0 0x418 | 92 | #define RK3368_EMMC_CON0 0x418 |
93 | #define RK3368_EMMC_CON1 0x41c | 93 | #define RK3368_EMMC_CON1 0x41c |
94 | 94 | ||
95 | #define RK3399_PLL_CON(x) RK2928_PLL_CON(x) | ||
96 | #define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100) | ||
97 | #define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300) | ||
98 | #define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400) | ||
99 | #define RK3399_GLB_SRST_FST 0x500 | ||
100 | #define RK3399_GLB_SRST_SND 0x504 | ||
101 | #define RK3399_GLB_CNT_TH 0x508 | ||
102 | #define RK3399_MISC_CON 0x50c | ||
103 | #define RK3399_RST_CON 0x510 | ||
104 | #define RK3399_RST_ST 0x514 | ||
105 | #define RK3399_SDMMC_CON0 0x580 | ||
106 | #define RK3399_SDMMC_CON1 0x584 | ||
107 | #define RK3399_SDIO_CON0 0x588 | ||
108 | #define RK3399_SDIO_CON1 0x58c | ||
109 | |||
110 | #define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x) | ||
111 | #define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80) | ||
112 | #define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100) | ||
113 | #define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110) | ||
114 | |||
95 | enum rockchip_pll_type { | 115 | enum rockchip_pll_type { |
96 | pll_rk3036, | 116 | pll_rk3036, |
97 | pll_rk3066, | 117 | pll_rk3066, |
118 | pll_rk3399, | ||
98 | }; | 119 | }; |
99 | 120 | ||
100 | #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ | 121 | #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ |
@@ -127,13 +148,29 @@ enum rockchip_pll_type { | |||
127 | .nb = _nb, \ | 148 | .nb = _nb, \ |
128 | } | 149 | } |
129 | 150 | ||
151 | /** | ||
152 | * struct rockchip_clk_provider - information about clock provider | ||
153 | * @reg_base: virtual address for the register base. | ||
154 | * @clk_data: holds clock related data like clk* and number of clocks. | ||
155 | * @cru_node: device-node of the clock-provider | ||
156 | * @grf: regmap of the general-register-files syscon | ||
157 | * @lock: maintains exclusion between callbacks for a given clock-provider. | ||
158 | */ | ||
159 | struct rockchip_clk_provider { | ||
160 | void __iomem *reg_base; | ||
161 | struct clk_onecell_data clk_data; | ||
162 | struct device_node *cru_node; | ||
163 | struct regmap *grf; | ||
164 | spinlock_t lock; | ||
165 | }; | ||
166 | |||
130 | struct rockchip_pll_rate_table { | 167 | struct rockchip_pll_rate_table { |
131 | unsigned long rate; | 168 | unsigned long rate; |
132 | unsigned int nr; | 169 | unsigned int nr; |
133 | unsigned int nf; | 170 | unsigned int nf; |
134 | unsigned int no; | 171 | unsigned int no; |
135 | unsigned int nb; | 172 | unsigned int nb; |
136 | /* for RK3036 */ | 173 | /* for RK3036/RK3399 */ |
137 | unsigned int fbdiv; | 174 | unsigned int fbdiv; |
138 | unsigned int postdiv1; | 175 | unsigned int postdiv1; |
139 | unsigned int refdiv; | 176 | unsigned int refdiv; |
@@ -143,10 +180,11 @@ struct rockchip_pll_rate_table { | |||
143 | }; | 180 | }; |
144 | 181 | ||
145 | /** | 182 | /** |
146 | * struct rockchip_pll_clock: information about pll clock | 183 | * struct rockchip_pll_clock - information about pll clock |
147 | * @id: platform specific id of the clock. | 184 | * @id: platform specific id of the clock. |
148 | * @name: name of this pll clock. | 185 | * @name: name of this pll clock. |
149 | * @parent_name: name of the parent clock. | 186 | * @parent_names: name of the parent clock. |
187 | * @num_parents: number of parents | ||
150 | * @flags: optional flags for basic clock. | 188 | * @flags: optional flags for basic clock. |
151 | * @con_offset: offset of the register for configuring the PLL. | 189 | * @con_offset: offset of the register for configuring the PLL. |
152 | * @mode_offset: offset of the register for configuring the PLL-mode. | 190 | * @mode_offset: offset of the register for configuring the PLL-mode. |
@@ -194,12 +232,13 @@ struct rockchip_pll_clock { | |||
194 | .rate_table = _rtable, \ | 232 | .rate_table = _rtable, \ |
195 | } | 233 | } |
196 | 234 | ||
197 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | 235 | struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, |
236 | enum rockchip_pll_type pll_type, | ||
198 | const char *name, const char *const *parent_names, | 237 | const char *name, const char *const *parent_names, |
199 | u8 num_parents, void __iomem *base, int con_offset, | 238 | u8 num_parents, int con_offset, int grf_lock_offset, |
200 | int grf_lock_offset, int lock_shift, int reg_mode, | 239 | int lock_shift, int mode_offset, int mode_shift, |
201 | int mode_shift, struct rockchip_pll_rate_table *rate_table, | 240 | struct rockchip_pll_rate_table *rate_table, |
202 | u8 clk_pll_flags, spinlock_t *lock); | 241 | u8 clk_pll_flags); |
203 | 242 | ||
204 | struct rockchip_cpuclk_clksel { | 243 | struct rockchip_cpuclk_clksel { |
205 | int reg; | 244 | int reg; |
@@ -213,18 +252,23 @@ struct rockchip_cpuclk_rate_table { | |||
213 | }; | 252 | }; |
214 | 253 | ||
215 | /** | 254 | /** |
216 | * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock | 255 | * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock |
217 | * @core_reg: register offset of the core settings register | 256 | * @core_reg: register offset of the core settings register |
218 | * @div_core_shift: core divider offset used to divide the pll value | 257 | * @div_core_shift: core divider offset used to divide the pll value |
219 | * @div_core_mask: core divider mask | 258 | * @div_core_mask: core divider mask |
259 | * @mux_core_alt: mux value to select alternate parent | ||
260 | * @mux_core_main: mux value to select main parent of core | ||
220 | * @mux_core_shift: offset of the core multiplexer | 261 | * @mux_core_shift: offset of the core multiplexer |
262 | * @mux_core_mask: core multiplexer mask | ||
221 | */ | 263 | */ |
222 | struct rockchip_cpuclk_reg_data { | 264 | struct rockchip_cpuclk_reg_data { |
223 | int core_reg; | 265 | int core_reg; |
224 | u8 div_core_shift; | 266 | u8 div_core_shift; |
225 | u32 div_core_mask; | 267 | u32 div_core_mask; |
226 | int mux_core_reg; | 268 | u8 mux_core_alt; |
269 | u8 mux_core_main; | ||
227 | u8 mux_core_shift; | 270 | u8 mux_core_shift; |
271 | u32 mux_core_mask; | ||
228 | }; | 272 | }; |
229 | 273 | ||
230 | struct clk *rockchip_clk_register_cpuclk(const char *name, | 274 | struct clk *rockchip_clk_register_cpuclk(const char *name, |
@@ -428,6 +472,22 @@ struct rockchip_clk_branch { | |||
428 | .child = ch, \ | 472 | .child = ch, \ |
429 | } | 473 | } |
430 | 474 | ||
475 | #define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \ | ||
476 | { \ | ||
477 | .id = _id, \ | ||
478 | .branch_type = branch_fraction_divider, \ | ||
479 | .name = cname, \ | ||
480 | .parent_names = (const char *[]){ pname }, \ | ||
481 | .num_parents = 1, \ | ||
482 | .flags = f, \ | ||
483 | .muxdiv_offset = mo, \ | ||
484 | .div_shift = 16, \ | ||
485 | .div_width = 16, \ | ||
486 | .div_flags = df, \ | ||
487 | .gate_offset = -1, \ | ||
488 | .child = ch, \ | ||
489 | } | ||
490 | |||
431 | #define MUX(_id, cname, pnames, f, o, s, w, mf) \ | 491 | #define MUX(_id, cname, pnames, f, o, s, w, mf) \ |
432 | { \ | 492 | { \ |
433 | .id = _id, \ | 493 | .id = _id, \ |
@@ -536,21 +596,27 @@ struct rockchip_clk_branch { | |||
536 | .gate_flags = gf, \ | 596 | .gate_flags = gf, \ |
537 | } | 597 | } |
538 | 598 | ||
539 | void rockchip_clk_init(struct device_node *np, void __iomem *base, | 599 | struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, |
540 | unsigned long nr_clks); | 600 | void __iomem *base, unsigned long nr_clks); |
541 | struct regmap *rockchip_clk_get_grf(void); | 601 | void rockchip_clk_of_add_provider(struct device_node *np, |
542 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); | 602 | struct rockchip_clk_provider *ctx); |
543 | void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, | 603 | void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, |
604 | struct clk *clk, unsigned int id); | ||
605 | void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, | ||
606 | struct rockchip_clk_branch *list, | ||
544 | unsigned int nr_clk); | 607 | unsigned int nr_clk); |
545 | void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, | 608 | void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, |
609 | struct rockchip_pll_clock *pll_list, | ||
546 | unsigned int nr_pll, int grf_lock_offset); | 610 | unsigned int nr_pll, int grf_lock_offset); |
547 | void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, | 611 | void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, |
612 | unsigned int lookup_id, const char *name, | ||
548 | const char *const *parent_names, u8 num_parents, | 613 | const char *const *parent_names, u8 num_parents, |
549 | const struct rockchip_cpuclk_reg_data *reg_data, | 614 | const struct rockchip_cpuclk_reg_data *reg_data, |
550 | const struct rockchip_cpuclk_rate_table *rates, | 615 | const struct rockchip_cpuclk_rate_table *rates, |
551 | int nrates); | 616 | int nrates); |
552 | void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); | 617 | void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); |
553 | void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)); | 618 | void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, |
619 | unsigned int reg, void (*cb)(void)); | ||
554 | 620 | ||
555 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) | 621 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) |
556 | 622 | ||
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index be03ed0fcb6b..92382cef9f90 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c | |||
@@ -554,8 +554,8 @@ static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = { | |||
554 | }; | 554 | }; |
555 | 555 | ||
556 | static struct samsung_div_clock exynos5800_div_clks[] __initdata = { | 556 | static struct samsung_div_clock exynos5800_div_clks[] __initdata = { |
557 | DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3), | 557 | DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore", |
558 | 558 | "mout_aclk400_wcore", DIV_TOP0, 16, 3), | |
559 | DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", | 559 | DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", |
560 | DIV_TOP8, 16, 3), | 560 | DIV_TOP8, 16, 3), |
561 | DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam", | 561 | DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam", |
@@ -607,8 +607,8 @@ static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { | |||
607 | }; | 607 | }; |
608 | 608 | ||
609 | static struct samsung_div_clock exynos5420_div_clks[] __initdata = { | 609 | static struct samsung_div_clock exynos5420_div_clks[] __initdata = { |
610 | DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll", | 610 | DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore", |
611 | DIV_TOP0, 16, 3), | 611 | "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3), |
612 | }; | 612 | }; |
613 | 613 | ||
614 | static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { | 614 | static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { |
@@ -785,31 +785,47 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = { | |||
785 | DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3), | 785 | DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3), |
786 | DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), | 786 | DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), |
787 | 787 | ||
788 | DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3), | 788 | DIV(CLK_DOUT_ACLK400_ISP, "dout_aclk400_isp", "mout_aclk400_isp", |
789 | DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3), | 789 | DIV_TOP0, 0, 3), |
790 | DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3), | 790 | DIV(CLK_DOUT_ACLK400_MSCL, "dout_aclk400_mscl", "mout_aclk400_mscl", |
791 | DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3), | 791 | DIV_TOP0, 4, 3), |
792 | DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3), | 792 | DIV(CLK_DOUT_ACLK200, "dout_aclk200", "mout_aclk200", |
793 | DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3), | 793 | DIV_TOP0, 8, 3), |
794 | DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3), | 794 | DIV(CLK_DOUT_ACLK200_FSYS2, "dout_aclk200_fsys2", "mout_aclk200_fsys2", |
795 | 795 | DIV_TOP0, 12, 3), | |
796 | DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl", | 796 | DIV(CLK_DOUT_ACLK100_NOC, "dout_aclk100_noc", "mout_aclk100_noc", |
797 | DIV_TOP1, 0, 3), | 797 | DIV_TOP0, 20, 3), |
798 | DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp", | 798 | DIV(CLK_DOUT_PCLK200_FSYS, "dout_pclk200_fsys", "mout_pclk200_fsys", |
799 | DIV_TOP1, 4, 3), | 799 | DIV_TOP0, 24, 3), |
800 | DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6), | 800 | DIV(CLK_DOUT_ACLK200_FSYS, "dout_aclk200_fsys", "mout_aclk200_fsys", |
801 | DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0", | 801 | DIV_TOP0, 28, 3), |
802 | DIV_TOP1, 16, 3), | 802 | DIV(CLK_DOUT_ACLK333_432_GSCL, "dout_aclk333_432_gscl", |
803 | DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3), | 803 | "mout_aclk333_432_gscl", DIV_TOP1, 0, 3), |
804 | DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3), | 804 | DIV(CLK_DOUT_ACLK333_432_ISP, "dout_aclk333_432_isp", |
805 | DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3), | 805 | "mout_aclk333_432_isp", DIV_TOP1, 4, 3), |
806 | 806 | DIV(CLK_DOUT_ACLK66, "dout_aclk66", "mout_aclk66", | |
807 | DIV(0, "dout_aclk333_g2d", "mout_aclk333_g2d", DIV_TOP2, 8, 3), | 807 | DIV_TOP1, 8, 6), |
808 | DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3), | 808 | DIV(CLK_DOUT_ACLK333_432_ISP0, "dout_aclk333_432_isp0", |
809 | DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3), | 809 | "mout_aclk333_432_isp0", DIV_TOP1, 16, 3), |
810 | DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3), | 810 | DIV(CLK_DOUT_ACLK266, "dout_aclk266", "mout_aclk266", |
811 | DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3), | 811 | DIV_TOP1, 20, 3), |
812 | DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3), | 812 | DIV(CLK_DOUT_ACLK166, "dout_aclk166", "mout_aclk166", |
813 | DIV_TOP1, 24, 3), | ||
814 | DIV(CLK_DOUT_ACLK333, "dout_aclk333", "mout_aclk333", | ||
815 | DIV_TOP1, 28, 3), | ||
816 | |||
817 | DIV(CLK_DOUT_ACLK333_G2D, "dout_aclk333_g2d", "mout_aclk333_g2d", | ||
818 | DIV_TOP2, 8, 3), | ||
819 | DIV(CLK_DOUT_ACLK266_G2D, "dout_aclk266_g2d", "mout_aclk266_g2d", | ||
820 | DIV_TOP2, 12, 3), | ||
821 | DIV(CLK_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, | ||
822 | 16, 3), | ||
823 | DIV(CLK_DOUT_ACLK300_JPEG, "dout_aclk300_jpeg", "mout_aclk300_jpeg", | ||
824 | DIV_TOP2, 20, 3), | ||
825 | DIV(CLK_DOUT_ACLK300_DISP1, "dout_aclk300_disp1", | ||
826 | "mout_aclk300_disp1", DIV_TOP2, 24, 3), | ||
827 | DIV(CLK_DOUT_ACLK300_GSCL, "dout_aclk300_gscl", "mout_aclk300_gscl", | ||
828 | DIV_TOP2, 28, 3), | ||
813 | 829 | ||
814 | /* DISP1 Block */ | 830 | /* DISP1 Block */ |
815 | DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4), | 831 | DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4), |
@@ -817,7 +833,8 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = { | |||
817 | DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), | 833 | DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), |
818 | DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), | 834 | DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), |
819 | DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), | 835 | DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), |
820 | DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3), | 836 | DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1", |
837 | "mout_aclk400_disp1", DIV_TOP2, 4, 3), | ||
821 | 838 | ||
822 | /* Audio Block */ | 839 | /* Audio Block */ |
823 | DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), | 840 | DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), |
diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c index c5eaa9d16247..665fa681b2e1 100644 --- a/drivers/clk/sirf/clk-atlas6.c +++ b/drivers/clk/sirf/clk-atlas6.c | |||
@@ -130,10 +130,9 @@ static void __init atlas6_clk_init(struct device_node *np) | |||
130 | panic("unable to map clkc registers\n"); | 130 | panic("unable to map clkc registers\n"); |
131 | 131 | ||
132 | /* These are always available (RTC and 26MHz OSC)*/ | 132 | /* These are always available (RTC and 26MHz OSC)*/ |
133 | atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, | 133 | atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768); |
134 | CLK_IS_ROOT, 32768); | 134 | atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0, |
135 | atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, | 135 | 26000000); |
136 | CLK_IS_ROOT, 26000000); | ||
137 | 136 | ||
138 | for (i = pll1; i < maxclk; i++) { | 137 | for (i = pll1; i < maxclk; i++) { |
139 | atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]); | 138 | atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]); |
diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c index f92c40264342..aac1c8ec151a 100644 --- a/drivers/clk/sirf/clk-prima2.c +++ b/drivers/clk/sirf/clk-prima2.c | |||
@@ -129,10 +129,9 @@ static void __init prima2_clk_init(struct device_node *np) | |||
129 | panic("unable to map clkc registers\n"); | 129 | panic("unable to map clkc registers\n"); |
130 | 130 | ||
131 | /* These are always available (RTC and 26MHz OSC)*/ | 131 | /* These are always available (RTC and 26MHz OSC)*/ |
132 | prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, | 132 | prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768); |
133 | CLK_IS_ROOT, 32768); | 133 | prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0, |
134 | prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, | 134 | 26000000); |
135 | CLK_IS_ROOT, 26000000); | ||
136 | 135 | ||
137 | for (i = pll1; i < maxclk; i++) { | 136 | for (i = pll1; i < maxclk; i++) { |
138 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); | 137 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 3fd7901d48e4..39d2044a1f49 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile | |||
@@ -11,6 +11,9 @@ obj-y += clk-a10-ve.o | |||
11 | obj-y += clk-a20-gmac.o | 11 | obj-y += clk-a20-gmac.o |
12 | obj-y += clk-mod0.o | 12 | obj-y += clk-mod0.o |
13 | obj-y += clk-simple-gates.o | 13 | obj-y += clk-simple-gates.o |
14 | obj-y += clk-sun4i-display.o | ||
15 | obj-y += clk-sun4i-pll3.o | ||
16 | obj-y += clk-sun4i-tcon-ch1.o | ||
14 | obj-y += clk-sun8i-bus-gates.o | 17 | obj-y += clk-sun8i-bus-gates.o |
15 | obj-y += clk-sun8i-mbus.o | 18 | obj-y += clk-sun8i-mbus.o |
16 | obj-y += clk-sun9i-core.o | 19 | obj-y += clk-sun9i-core.o |
diff --git a/drivers/clk/sunxi/clk-a10-hosc.c b/drivers/clk/sunxi/clk-a10-hosc.c index 6b598c6a0213..dca532431394 100644 --- a/drivers/clk/sunxi/clk-a10-hosc.c +++ b/drivers/clk/sunxi/clk-a10-hosc.c | |||
@@ -54,8 +54,7 @@ static void __init sun4i_osc_clk_setup(struct device_node *node) | |||
54 | NULL, 0, | 54 | NULL, 0, |
55 | NULL, NULL, | 55 | NULL, NULL, |
56 | &fixed->hw, &clk_fixed_rate_ops, | 56 | &fixed->hw, &clk_fixed_rate_ops, |
57 | &gate->hw, &clk_gate_ops, | 57 | &gate->hw, &clk_gate_ops, 0); |
58 | CLK_IS_ROOT); | ||
59 | 58 | ||
60 | if (IS_ERR(clk)) | 59 | if (IS_ERR(clk)) |
61 | goto err_free_gate; | 60 | goto err_free_gate; |
diff --git a/drivers/clk/sunxi/clk-a10-mod1.c b/drivers/clk/sunxi/clk-a10-mod1.c index e9d870de165c..e2819fa09637 100644 --- a/drivers/clk/sunxi/clk-a10-mod1.c +++ b/drivers/clk/sunxi/clk-a10-mod1.c | |||
@@ -62,7 +62,7 @@ static void __init sun4i_mod1_clk_setup(struct device_node *node) | |||
62 | clk = clk_register_composite(NULL, clk_name, parents, i, | 62 | clk = clk_register_composite(NULL, clk_name, parents, i, |
63 | &mux->hw, &clk_mux_ops, | 63 | &mux->hw, &clk_mux_ops, |
64 | NULL, NULL, | 64 | NULL, NULL, |
65 | &gate->hw, &clk_gate_ops, 0); | 65 | &gate->hw, &clk_gate_ops, CLK_SET_RATE_PARENT); |
66 | if (IS_ERR(clk)) | 66 | if (IS_ERR(clk)) |
67 | goto err_free_gate; | 67 | goto err_free_gate; |
68 | 68 | ||
diff --git a/drivers/clk/sunxi/clk-sun4i-display.c b/drivers/clk/sunxi/clk-sun4i-display.c new file mode 100644 index 000000000000..445a7498d6df --- /dev/null +++ b/drivers/clk/sunxi/clk-sun4i-display.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Maxime Ripard | ||
3 | * | ||
4 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/reset-controller.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | |||
24 | struct sun4i_a10_display_clk_data { | ||
25 | bool has_div; | ||
26 | u8 num_rst; | ||
27 | u8 parents; | ||
28 | |||
29 | u8 offset_en; | ||
30 | u8 offset_div; | ||
31 | u8 offset_mux; | ||
32 | u8 offset_rst; | ||
33 | |||
34 | u8 width_div; | ||
35 | u8 width_mux; | ||
36 | }; | ||
37 | |||
38 | struct reset_data { | ||
39 | void __iomem *reg; | ||
40 | spinlock_t *lock; | ||
41 | struct reset_controller_dev rcdev; | ||
42 | u8 offset; | ||
43 | }; | ||
44 | |||
45 | static DEFINE_SPINLOCK(sun4i_a10_display_lock); | ||
46 | |||
47 | static inline struct reset_data *rcdev_to_reset_data(struct reset_controller_dev *rcdev) | ||
48 | { | ||
49 | return container_of(rcdev, struct reset_data, rcdev); | ||
50 | }; | ||
51 | |||
52 | static int sun4i_a10_display_assert(struct reset_controller_dev *rcdev, | ||
53 | unsigned long id) | ||
54 | { | ||
55 | struct reset_data *data = rcdev_to_reset_data(rcdev); | ||
56 | unsigned long flags; | ||
57 | u32 reg; | ||
58 | |||
59 | spin_lock_irqsave(data->lock, flags); | ||
60 | |||
61 | reg = readl(data->reg); | ||
62 | writel(reg & ~BIT(data->offset + id), data->reg); | ||
63 | |||
64 | spin_unlock_irqrestore(data->lock, flags); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int sun4i_a10_display_deassert(struct reset_controller_dev *rcdev, | ||
70 | unsigned long id) | ||
71 | { | ||
72 | struct reset_data *data = rcdev_to_reset_data(rcdev); | ||
73 | unsigned long flags; | ||
74 | u32 reg; | ||
75 | |||
76 | spin_lock_irqsave(data->lock, flags); | ||
77 | |||
78 | reg = readl(data->reg); | ||
79 | writel(reg | BIT(data->offset + id), data->reg); | ||
80 | |||
81 | spin_unlock_irqrestore(data->lock, flags); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int sun4i_a10_display_status(struct reset_controller_dev *rcdev, | ||
87 | unsigned long id) | ||
88 | { | ||
89 | struct reset_data *data = rcdev_to_reset_data(rcdev); | ||
90 | |||
91 | return !(readl(data->reg) & BIT(data->offset + id)); | ||
92 | } | ||
93 | |||
94 | static const struct reset_control_ops sun4i_a10_display_reset_ops = { | ||
95 | .assert = sun4i_a10_display_assert, | ||
96 | .deassert = sun4i_a10_display_deassert, | ||
97 | .status = sun4i_a10_display_status, | ||
98 | }; | ||
99 | |||
100 | static int sun4i_a10_display_reset_xlate(struct reset_controller_dev *rcdev, | ||
101 | const struct of_phandle_args *spec) | ||
102 | { | ||
103 | /* We only have a single reset signal */ | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static void __init sun4i_a10_display_init(struct device_node *node, | ||
108 | const struct sun4i_a10_display_clk_data *data) | ||
109 | { | ||
110 | const char *parents[4]; | ||
111 | const char *clk_name = node->name; | ||
112 | struct reset_data *reset_data; | ||
113 | struct clk_divider *div = NULL; | ||
114 | struct clk_gate *gate; | ||
115 | struct resource res; | ||
116 | struct clk_mux *mux; | ||
117 | void __iomem *reg; | ||
118 | struct clk *clk; | ||
119 | int ret; | ||
120 | |||
121 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
122 | |||
123 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
124 | if (IS_ERR(reg)) { | ||
125 | pr_err("%s: Could not map the clock registers\n", clk_name); | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | ret = of_clk_parent_fill(node, parents, data->parents); | ||
130 | if (ret != data->parents) { | ||
131 | pr_err("%s: Could not retrieve the parents\n", clk_name); | ||
132 | goto unmap; | ||
133 | } | ||
134 | |||
135 | mux = kzalloc(sizeof(*mux), GFP_KERNEL); | ||
136 | if (!mux) | ||
137 | goto unmap; | ||
138 | |||
139 | mux->reg = reg; | ||
140 | mux->shift = data->offset_mux; | ||
141 | mux->mask = (1 << data->width_mux) - 1; | ||
142 | mux->lock = &sun4i_a10_display_lock; | ||
143 | |||
144 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
145 | if (!gate) | ||
146 | goto free_mux; | ||
147 | |||
148 | gate->reg = reg; | ||
149 | gate->bit_idx = data->offset_en; | ||
150 | gate->lock = &sun4i_a10_display_lock; | ||
151 | |||
152 | if (data->has_div) { | ||
153 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
154 | if (!div) | ||
155 | goto free_gate; | ||
156 | |||
157 | div->reg = reg; | ||
158 | div->shift = data->offset_div; | ||
159 | div->width = data->width_div; | ||
160 | div->lock = &sun4i_a10_display_lock; | ||
161 | } | ||
162 | |||
163 | clk = clk_register_composite(NULL, clk_name, | ||
164 | parents, data->parents, | ||
165 | &mux->hw, &clk_mux_ops, | ||
166 | data->has_div ? &div->hw : NULL, | ||
167 | data->has_div ? &clk_divider_ops : NULL, | ||
168 | &gate->hw, &clk_gate_ops, | ||
169 | 0); | ||
170 | if (IS_ERR(clk)) { | ||
171 | pr_err("%s: Couldn't register the clock\n", clk_name); | ||
172 | goto free_div; | ||
173 | } | ||
174 | |||
175 | ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
176 | if (ret) { | ||
177 | pr_err("%s: Couldn't register DT provider\n", clk_name); | ||
178 | goto free_clk; | ||
179 | } | ||
180 | |||
181 | if (!data->num_rst) | ||
182 | return; | ||
183 | |||
184 | reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); | ||
185 | if (!reset_data) | ||
186 | goto free_of_clk; | ||
187 | |||
188 | reset_data->reg = reg; | ||
189 | reset_data->offset = data->offset_rst; | ||
190 | reset_data->lock = &sun4i_a10_display_lock; | ||
191 | reset_data->rcdev.nr_resets = data->num_rst; | ||
192 | reset_data->rcdev.ops = &sun4i_a10_display_reset_ops; | ||
193 | reset_data->rcdev.of_node = node; | ||
194 | |||
195 | if (data->num_rst == 1) { | ||
196 | reset_data->rcdev.of_reset_n_cells = 0; | ||
197 | reset_data->rcdev.of_xlate = &sun4i_a10_display_reset_xlate; | ||
198 | } else { | ||
199 | reset_data->rcdev.of_reset_n_cells = 1; | ||
200 | } | ||
201 | |||
202 | if (reset_controller_register(&reset_data->rcdev)) { | ||
203 | pr_err("%s: Couldn't register the reset controller\n", | ||
204 | clk_name); | ||
205 | goto free_reset; | ||
206 | } | ||
207 | |||
208 | return; | ||
209 | |||
210 | free_reset: | ||
211 | kfree(reset_data); | ||
212 | free_of_clk: | ||
213 | of_clk_del_provider(node); | ||
214 | free_clk: | ||
215 | clk_unregister_composite(clk); | ||
216 | free_div: | ||
217 | kfree(div); | ||
218 | free_gate: | ||
219 | kfree(gate); | ||
220 | free_mux: | ||
221 | kfree(mux); | ||
222 | unmap: | ||
223 | iounmap(reg); | ||
224 | of_address_to_resource(node, 0, &res); | ||
225 | release_mem_region(res.start, resource_size(&res)); | ||
226 | } | ||
227 | |||
228 | static const struct sun4i_a10_display_clk_data sun4i_a10_tcon_ch0_data __initconst = { | ||
229 | .num_rst = 2, | ||
230 | .parents = 4, | ||
231 | .offset_en = 31, | ||
232 | .offset_rst = 29, | ||
233 | .offset_mux = 24, | ||
234 | .width_mux = 2, | ||
235 | }; | ||
236 | |||
237 | static void __init sun4i_a10_tcon_ch0_setup(struct device_node *node) | ||
238 | { | ||
239 | sun4i_a10_display_init(node, &sun4i_a10_tcon_ch0_data); | ||
240 | } | ||
241 | CLK_OF_DECLARE(sun4i_a10_tcon_ch0, "allwinner,sun4i-a10-tcon-ch0-clk", | ||
242 | sun4i_a10_tcon_ch0_setup); | ||
243 | |||
244 | static const struct sun4i_a10_display_clk_data sun4i_a10_display_data __initconst = { | ||
245 | .has_div = true, | ||
246 | .num_rst = 1, | ||
247 | .parents = 3, | ||
248 | .offset_en = 31, | ||
249 | .offset_rst = 30, | ||
250 | .offset_mux = 24, | ||
251 | .offset_div = 0, | ||
252 | .width_mux = 2, | ||
253 | .width_div = 4, | ||
254 | }; | ||
255 | |||
256 | static void __init sun4i_a10_display_setup(struct device_node *node) | ||
257 | { | ||
258 | sun4i_a10_display_init(node, &sun4i_a10_display_data); | ||
259 | } | ||
260 | CLK_OF_DECLARE(sun4i_a10_display, "allwinner,sun4i-a10-display-clk", | ||
261 | sun4i_a10_display_setup); | ||
diff --git a/drivers/clk/sunxi/clk-sun4i-pll3.c b/drivers/clk/sunxi/clk-sun4i-pll3.c new file mode 100644 index 000000000000..f66267e77d9c --- /dev/null +++ b/drivers/clk/sunxi/clk-sun4i-pll3.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Maxime Ripard | ||
3 | * | ||
4 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | |||
23 | #define SUN4I_A10_PLL3_GATE_BIT 31 | ||
24 | #define SUN4I_A10_PLL3_DIV_WIDTH 7 | ||
25 | #define SUN4I_A10_PLL3_DIV_SHIFT 0 | ||
26 | |||
27 | static DEFINE_SPINLOCK(sun4i_a10_pll3_lock); | ||
28 | |||
29 | static void __init sun4i_a10_pll3_setup(struct device_node *node) | ||
30 | { | ||
31 | const char *clk_name = node->name, *parent; | ||
32 | struct clk_multiplier *mult; | ||
33 | struct clk_gate *gate; | ||
34 | struct resource res; | ||
35 | void __iomem *reg; | ||
36 | struct clk *clk; | ||
37 | int ret; | ||
38 | |||
39 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
40 | parent = of_clk_get_parent_name(node, 0); | ||
41 | |||
42 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
43 | if (IS_ERR(reg)) { | ||
44 | pr_err("%s: Could not map the clock registers\n", clk_name); | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
49 | if (!gate) | ||
50 | goto err_unmap; | ||
51 | |||
52 | gate->reg = reg; | ||
53 | gate->bit_idx = SUN4I_A10_PLL3_GATE_BIT; | ||
54 | gate->lock = &sun4i_a10_pll3_lock; | ||
55 | |||
56 | mult = kzalloc(sizeof(*mult), GFP_KERNEL); | ||
57 | if (!mult) | ||
58 | goto err_free_gate; | ||
59 | |||
60 | mult->reg = reg; | ||
61 | mult->shift = SUN4I_A10_PLL3_DIV_SHIFT; | ||
62 | mult->width = SUN4I_A10_PLL3_DIV_WIDTH; | ||
63 | mult->lock = &sun4i_a10_pll3_lock; | ||
64 | |||
65 | clk = clk_register_composite(NULL, clk_name, | ||
66 | &parent, 1, | ||
67 | NULL, NULL, | ||
68 | &mult->hw, &clk_multiplier_ops, | ||
69 | &gate->hw, &clk_gate_ops, | ||
70 | 0); | ||
71 | if (IS_ERR(clk)) { | ||
72 | pr_err("%s: Couldn't register the clock\n", clk_name); | ||
73 | goto err_free_mult; | ||
74 | } | ||
75 | |||
76 | ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
77 | if (ret) { | ||
78 | pr_err("%s: Couldn't register DT provider\n", | ||
79 | clk_name); | ||
80 | goto err_clk_unregister; | ||
81 | } | ||
82 | |||
83 | return; | ||
84 | |||
85 | err_clk_unregister: | ||
86 | clk_unregister_composite(clk); | ||
87 | err_free_mult: | ||
88 | kfree(mult); | ||
89 | err_free_gate: | ||
90 | kfree(gate); | ||
91 | err_unmap: | ||
92 | iounmap(reg); | ||
93 | of_address_to_resource(node, 0, &res); | ||
94 | release_mem_region(res.start, resource_size(&res)); | ||
95 | } | ||
96 | |||
97 | CLK_OF_DECLARE(sun4i_a10_pll3, "allwinner,sun4i-a10-pll3-clk", | ||
98 | sun4i_a10_pll3_setup); | ||
diff --git a/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c b/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c new file mode 100644 index 000000000000..98a4582de56a --- /dev/null +++ b/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Maxime Ripard | ||
3 | * | ||
4 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | |||
23 | #define TCON_CH1_SCLK2_PARENTS 4 | ||
24 | |||
25 | #define TCON_CH1_SCLK2_GATE_BIT BIT(31) | ||
26 | #define TCON_CH1_SCLK2_MUX_MASK 3 | ||
27 | #define TCON_CH1_SCLK2_MUX_SHIFT 24 | ||
28 | #define TCON_CH1_SCLK2_DIV_MASK 0xf | ||
29 | #define TCON_CH1_SCLK2_DIV_SHIFT 0 | ||
30 | |||
31 | #define TCON_CH1_SCLK1_GATE_BIT BIT(15) | ||
32 | #define TCON_CH1_SCLK1_HALF_BIT BIT(11) | ||
33 | |||
34 | struct tcon_ch1_clk { | ||
35 | struct clk_hw hw; | ||
36 | spinlock_t lock; | ||
37 | void __iomem *reg; | ||
38 | }; | ||
39 | |||
40 | #define hw_to_tclk(hw) container_of(hw, struct tcon_ch1_clk, hw) | ||
41 | |||
42 | static void tcon_ch1_disable(struct clk_hw *hw) | ||
43 | { | ||
44 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
45 | unsigned long flags; | ||
46 | u32 reg; | ||
47 | |||
48 | spin_lock_irqsave(&tclk->lock, flags); | ||
49 | reg = readl(tclk->reg); | ||
50 | reg &= ~(TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT); | ||
51 | writel(reg, tclk->reg); | ||
52 | spin_unlock_irqrestore(&tclk->lock, flags); | ||
53 | } | ||
54 | |||
55 | static int tcon_ch1_enable(struct clk_hw *hw) | ||
56 | { | ||
57 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
58 | unsigned long flags; | ||
59 | u32 reg; | ||
60 | |||
61 | spin_lock_irqsave(&tclk->lock, flags); | ||
62 | reg = readl(tclk->reg); | ||
63 | reg |= TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT; | ||
64 | writel(reg, tclk->reg); | ||
65 | spin_unlock_irqrestore(&tclk->lock, flags); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int tcon_ch1_is_enabled(struct clk_hw *hw) | ||
71 | { | ||
72 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
73 | u32 reg; | ||
74 | |||
75 | reg = readl(tclk->reg); | ||
76 | return reg & (TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT); | ||
77 | } | ||
78 | |||
79 | static u8 tcon_ch1_get_parent(struct clk_hw *hw) | ||
80 | { | ||
81 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
82 | int num_parents = clk_hw_get_num_parents(hw); | ||
83 | u32 reg; | ||
84 | |||
85 | reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT; | ||
86 | reg &= reg >> TCON_CH1_SCLK2_MUX_MASK; | ||
87 | |||
88 | if (reg >= num_parents) | ||
89 | return -EINVAL; | ||
90 | |||
91 | return reg; | ||
92 | } | ||
93 | |||
94 | static int tcon_ch1_set_parent(struct clk_hw *hw, u8 index) | ||
95 | { | ||
96 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
97 | unsigned long flags; | ||
98 | u32 reg; | ||
99 | |||
100 | spin_lock_irqsave(&tclk->lock, flags); | ||
101 | reg = readl(tclk->reg); | ||
102 | reg &= ~(TCON_CH1_SCLK2_MUX_MASK << TCON_CH1_SCLK2_MUX_SHIFT); | ||
103 | reg |= index << TCON_CH1_SCLK2_MUX_SHIFT; | ||
104 | writel(reg, tclk->reg); | ||
105 | spin_unlock_irqrestore(&tclk->lock, flags); | ||
106 | |||
107 | return 0; | ||
108 | }; | ||
109 | |||
110 | static unsigned long tcon_ch1_calc_divider(unsigned long rate, | ||
111 | unsigned long parent_rate, | ||
112 | u8 *div, | ||
113 | bool *half) | ||
114 | { | ||
115 | unsigned long best_rate = 0; | ||
116 | u8 best_m = 0, m; | ||
117 | bool is_double; | ||
118 | |||
119 | for (m = 1; m < 16; m++) { | ||
120 | u8 d; | ||
121 | |||
122 | for (d = 1; d < 3; d++) { | ||
123 | unsigned long tmp_rate; | ||
124 | |||
125 | tmp_rate = parent_rate / m / d; | ||
126 | |||
127 | if (tmp_rate > rate) | ||
128 | continue; | ||
129 | |||
130 | if (!best_rate || | ||
131 | (rate - tmp_rate) < (rate - best_rate)) { | ||
132 | best_rate = tmp_rate; | ||
133 | best_m = m; | ||
134 | is_double = d; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | if (div && half) { | ||
140 | *div = best_m; | ||
141 | *half = is_double; | ||
142 | } | ||
143 | |||
144 | return best_rate; | ||
145 | } | ||
146 | |||
147 | static int tcon_ch1_determine_rate(struct clk_hw *hw, | ||
148 | struct clk_rate_request *req) | ||
149 | { | ||
150 | long best_rate = -EINVAL; | ||
151 | int i; | ||
152 | |||
153 | for (i = 0; i < clk_hw_get_num_parents(hw); i++) { | ||
154 | unsigned long parent_rate; | ||
155 | unsigned long tmp_rate; | ||
156 | struct clk_hw *parent; | ||
157 | |||
158 | parent = clk_hw_get_parent_by_index(hw, i); | ||
159 | if (!parent) | ||
160 | continue; | ||
161 | |||
162 | parent_rate = clk_hw_get_rate(parent); | ||
163 | |||
164 | tmp_rate = tcon_ch1_calc_divider(req->rate, parent_rate, | ||
165 | NULL, NULL); | ||
166 | |||
167 | if (best_rate < 0 || | ||
168 | (req->rate - tmp_rate) < (req->rate - best_rate)) { | ||
169 | best_rate = tmp_rate; | ||
170 | req->best_parent_rate = parent_rate; | ||
171 | req->best_parent_hw = parent; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | if (best_rate < 0) | ||
176 | return best_rate; | ||
177 | |||
178 | req->rate = best_rate; | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static unsigned long tcon_ch1_recalc_rate(struct clk_hw *hw, | ||
183 | unsigned long parent_rate) | ||
184 | { | ||
185 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
186 | u32 reg; | ||
187 | |||
188 | reg = readl(tclk->reg); | ||
189 | |||
190 | parent_rate /= (reg & TCON_CH1_SCLK2_DIV_MASK) + 1; | ||
191 | |||
192 | if (reg & TCON_CH1_SCLK1_HALF_BIT) | ||
193 | parent_rate /= 2; | ||
194 | |||
195 | return parent_rate; | ||
196 | } | ||
197 | |||
198 | static int tcon_ch1_set_rate(struct clk_hw *hw, unsigned long rate, | ||
199 | unsigned long parent_rate) | ||
200 | { | ||
201 | struct tcon_ch1_clk *tclk = hw_to_tclk(hw); | ||
202 | unsigned long flags; | ||
203 | bool half; | ||
204 | u8 div_m; | ||
205 | u32 reg; | ||
206 | |||
207 | tcon_ch1_calc_divider(rate, parent_rate, &div_m, &half); | ||
208 | |||
209 | spin_lock_irqsave(&tclk->lock, flags); | ||
210 | reg = readl(tclk->reg); | ||
211 | reg &= ~(TCON_CH1_SCLK2_DIV_MASK | TCON_CH1_SCLK1_HALF_BIT); | ||
212 | reg |= (div_m - 1) & TCON_CH1_SCLK2_DIV_MASK; | ||
213 | |||
214 | if (half) | ||
215 | reg |= TCON_CH1_SCLK1_HALF_BIT; | ||
216 | |||
217 | writel(reg, tclk->reg); | ||
218 | spin_unlock_irqrestore(&tclk->lock, flags); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static const struct clk_ops tcon_ch1_ops = { | ||
224 | .disable = tcon_ch1_disable, | ||
225 | .enable = tcon_ch1_enable, | ||
226 | .is_enabled = tcon_ch1_is_enabled, | ||
227 | |||
228 | .get_parent = tcon_ch1_get_parent, | ||
229 | .set_parent = tcon_ch1_set_parent, | ||
230 | |||
231 | .determine_rate = tcon_ch1_determine_rate, | ||
232 | .recalc_rate = tcon_ch1_recalc_rate, | ||
233 | .set_rate = tcon_ch1_set_rate, | ||
234 | }; | ||
235 | |||
236 | static void __init tcon_ch1_setup(struct device_node *node) | ||
237 | { | ||
238 | const char *parents[TCON_CH1_SCLK2_PARENTS]; | ||
239 | const char *clk_name = node->name; | ||
240 | struct clk_init_data init; | ||
241 | struct tcon_ch1_clk *tclk; | ||
242 | struct resource res; | ||
243 | struct clk *clk; | ||
244 | void __iomem *reg; | ||
245 | int ret; | ||
246 | |||
247 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
248 | |||
249 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | ||
250 | if (IS_ERR(reg)) { | ||
251 | pr_err("%s: Could not map the clock registers\n", clk_name); | ||
252 | return; | ||
253 | } | ||
254 | |||
255 | ret = of_clk_parent_fill(node, parents, TCON_CH1_SCLK2_PARENTS); | ||
256 | if (ret != TCON_CH1_SCLK2_PARENTS) { | ||
257 | pr_err("%s Could not retrieve the parents\n", clk_name); | ||
258 | goto err_unmap; | ||
259 | } | ||
260 | |||
261 | tclk = kzalloc(sizeof(*tclk), GFP_KERNEL); | ||
262 | if (!tclk) | ||
263 | goto err_unmap; | ||
264 | |||
265 | init.name = clk_name; | ||
266 | init.ops = &tcon_ch1_ops; | ||
267 | init.parent_names = parents; | ||
268 | init.num_parents = TCON_CH1_SCLK2_PARENTS; | ||
269 | init.flags = CLK_SET_RATE_PARENT; | ||
270 | |||
271 | tclk->reg = reg; | ||
272 | tclk->hw.init = &init; | ||
273 | spin_lock_init(&tclk->lock); | ||
274 | |||
275 | clk = clk_register(NULL, &tclk->hw); | ||
276 | if (IS_ERR(clk)) { | ||
277 | pr_err("%s: Couldn't register the clock\n", clk_name); | ||
278 | goto err_free_data; | ||
279 | } | ||
280 | |||
281 | ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
282 | if (ret) { | ||
283 | pr_err("%s: Couldn't register our clock provider\n", clk_name); | ||
284 | goto err_unregister_clk; | ||
285 | } | ||
286 | |||
287 | return; | ||
288 | |||
289 | err_unregister_clk: | ||
290 | clk_unregister(clk); | ||
291 | err_free_data: | ||
292 | kfree(tclk); | ||
293 | err_unmap: | ||
294 | iounmap(reg); | ||
295 | of_address_to_resource(node, 0, &res); | ||
296 | release_mem_region(res.start, resource_size(&res)); | ||
297 | } | ||
298 | |||
299 | CLK_OF_DECLARE(tcon_ch1, "allwinner,sun4i-a10-tcon-ch1-clk", | ||
300 | tcon_ch1_setup); | ||
diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index 028dd832a39f..716737388b7d 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c | |||
@@ -106,7 +106,7 @@ static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) | |||
106 | 106 | ||
107 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 107 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
108 | /* one clock/reset pair per word */ | 108 | /* one clock/reset pair per word */ |
109 | count = DIV_ROUND_UP((r->end - r->start + 1), SUN9I_MMC_WIDTH); | 109 | count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH); |
110 | data->membase = devm_ioremap_resource(&pdev->dev, r); | 110 | data->membase = devm_ioremap_resource(&pdev->dev, r); |
111 | if (IS_ERR(data->membase)) | 111 | if (IS_ERR(data->membase)) |
112 | return PTR_ERR(data->membase); | 112 | return PTR_ERR(data->membase); |
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 91de0a006773..838b22aa8b67 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -523,21 +523,12 @@ static const struct factors_data sun4i_pll5_data __initconst = { | |||
523 | .enable = 31, | 523 | .enable = 31, |
524 | .table = &sun4i_pll5_config, | 524 | .table = &sun4i_pll5_config, |
525 | .getter = sun4i_get_pll5_factors, | 525 | .getter = sun4i_get_pll5_factors, |
526 | .name = "pll5", | ||
527 | }; | ||
528 | |||
529 | static const struct factors_data sun4i_pll6_data __initconst = { | ||
530 | .enable = 31, | ||
531 | .table = &sun4i_pll5_config, | ||
532 | .getter = sun4i_get_pll5_factors, | ||
533 | .name = "pll6", | ||
534 | }; | 526 | }; |
535 | 527 | ||
536 | static const struct factors_data sun6i_a31_pll6_data __initconst = { | 528 | static const struct factors_data sun6i_a31_pll6_data __initconst = { |
537 | .enable = 31, | 529 | .enable = 31, |
538 | .table = &sun6i_a31_pll6_config, | 530 | .table = &sun6i_a31_pll6_config, |
539 | .getter = sun6i_a31_get_pll6_factors, | 531 | .getter = sun6i_a31_get_pll6_factors, |
540 | .name = "pll6x2", | ||
541 | }; | 532 | }; |
542 | 533 | ||
543 | static const struct factors_data sun5i_a13_ahb_data __initconst = { | 534 | static const struct factors_data sun5i_a13_ahb_data __initconst = { |
@@ -933,7 +924,7 @@ static const struct divs_data pll5_divs_data __initconst = { | |||
933 | }; | 924 | }; |
934 | 925 | ||
935 | static const struct divs_data pll6_divs_data __initconst = { | 926 | static const struct divs_data pll6_divs_data __initconst = { |
936 | .factors = &sun4i_pll6_data, | 927 | .factors = &sun4i_pll5_data, |
937 | .ndivs = 4, | 928 | .ndivs = 4, |
938 | .div = { | 929 | .div = { |
939 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ | 930 | { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ |
@@ -975,6 +966,8 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, | |||
975 | struct clk_gate *gate = NULL; | 966 | struct clk_gate *gate = NULL; |
976 | struct clk_fixed_factor *fix_factor; | 967 | struct clk_fixed_factor *fix_factor; |
977 | struct clk_divider *divider; | 968 | struct clk_divider *divider; |
969 | struct factors_data factors = *data->factors; | ||
970 | char *derived_name = NULL; | ||
978 | void __iomem *reg; | 971 | void __iomem *reg; |
979 | int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; | 972 | int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; |
980 | int flags, clkflags; | 973 | int flags, clkflags; |
@@ -983,11 +976,37 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, | |||
983 | if (data->ndivs) | 976 | if (data->ndivs) |
984 | ndivs = data->ndivs; | 977 | ndivs = data->ndivs; |
985 | 978 | ||
979 | /* Try to find a name for base factor clock */ | ||
980 | for (i = 0; i < ndivs; i++) { | ||
981 | if (data->div[i].self) { | ||
982 | of_property_read_string_index(node, "clock-output-names", | ||
983 | i, &factors.name); | ||
984 | break; | ||
985 | } | ||
986 | } | ||
987 | /* If we don't have a .self clk use the first output-name up to '_' */ | ||
988 | if (factors.name == NULL) { | ||
989 | char *endp; | ||
990 | |||
991 | of_property_read_string_index(node, "clock-output-names", | ||
992 | 0, &clk_name); | ||
993 | endp = strchr(clk_name, '_'); | ||
994 | if (endp) { | ||
995 | derived_name = kstrndup(clk_name, endp - clk_name, | ||
996 | GFP_KERNEL); | ||
997 | factors.name = derived_name; | ||
998 | } else { | ||
999 | factors.name = clk_name; | ||
1000 | } | ||
1001 | } | ||
1002 | |||
986 | /* Set up factor clock that we will be dividing */ | 1003 | /* Set up factor clock that we will be dividing */ |
987 | pclk = sunxi_factors_clk_setup(node, data->factors); | 1004 | pclk = sunxi_factors_clk_setup(node, &factors); |
988 | if (!pclk) | 1005 | if (!pclk) |
989 | return NULL; | 1006 | return NULL; |
1007 | |||
990 | parent = __clk_get_name(pclk); | 1008 | parent = __clk_get_name(pclk); |
1009 | kfree(derived_name); | ||
991 | 1010 | ||
992 | reg = of_iomap(node, 0); | 1011 | reg = of_iomap(node, 0); |
993 | if (!reg) { | 1012 | if (!reg) { |
@@ -1127,3 +1146,41 @@ static void __init sun6i_pll6_clk_setup(struct device_node *node) | |||
1127 | } | 1146 | } |
1128 | CLK_OF_DECLARE(sun6i_pll6, "allwinner,sun6i-a31-pll6-clk", | 1147 | CLK_OF_DECLARE(sun6i_pll6, "allwinner,sun6i-a31-pll6-clk", |
1129 | sun6i_pll6_clk_setup); | 1148 | sun6i_pll6_clk_setup); |
1149 | |||
1150 | /* | ||
1151 | * sun6i display | ||
1152 | * | ||
1153 | * rate = parent_rate / (m + 1); | ||
1154 | */ | ||
1155 | static void sun6i_display_factors(struct factors_request *req) | ||
1156 | { | ||
1157 | u8 m; | ||
1158 | |||
1159 | if (req->rate > req->parent_rate) | ||
1160 | req->rate = req->parent_rate; | ||
1161 | |||
1162 | m = DIV_ROUND_UP(req->parent_rate, req->rate); | ||
1163 | |||
1164 | req->rate = req->parent_rate / m; | ||
1165 | req->m = m - 1; | ||
1166 | } | ||
1167 | |||
1168 | static const struct clk_factors_config sun6i_display_config = { | ||
1169 | .mshift = 0, | ||
1170 | .mwidth = 4, | ||
1171 | }; | ||
1172 | |||
1173 | static const struct factors_data sun6i_display_data __initconst = { | ||
1174 | .enable = 31, | ||
1175 | .mux = 24, | ||
1176 | .muxmask = BIT(2) | BIT(1) | BIT(0), | ||
1177 | .table = &sun6i_display_config, | ||
1178 | .getter = sun6i_display_factors, | ||
1179 | }; | ||
1180 | |||
1181 | static void __init sun6i_display_setup(struct device_node *node) | ||
1182 | { | ||
1183 | sunxi_factors_clk_setup(node, &sun6i_display_data); | ||
1184 | } | ||
1185 | CLK_OF_DECLARE(sun6i_display, "allwinner,sun6i-a31-display-clk", | ||
1186 | sun6i_display_setup); | ||
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 97984c503bbb..33fd0938d79e 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile | |||
@@ -3,6 +3,7 @@ obj-y += clk-audio-sync.o | |||
3 | obj-y += clk-dfll.o | 3 | obj-y += clk-dfll.o |
4 | obj-y += clk-divider.o | 4 | obj-y += clk-divider.o |
5 | obj-y += clk-periph.o | 5 | obj-y += clk-periph.o |
6 | obj-y += clk-periph-fixed.o | ||
6 | obj-y += clk-periph-gate.o | 7 | obj-y += clk-periph-gate.o |
7 | obj-y += clk-pll.o | 8 | obj-y += clk-pll.o |
8 | obj-y += clk-pll-out.o | 9 | obj-y += clk-pll-out.o |
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 19bfa07e24b1..f010562534eb 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/seq_file.h> | 55 | #include <linux/seq_file.h> |
56 | 56 | ||
57 | #include "clk-dfll.h" | 57 | #include "clk-dfll.h" |
58 | #include "cvb.h" | ||
58 | 59 | ||
59 | /* | 60 | /* |
60 | * DFLL control registers - access via dfll_{readl,writel} | 61 | * DFLL control registers - access via dfll_{readl,writel} |
@@ -442,8 +443,8 @@ static void dfll_tune_low(struct tegra_dfll *td) | |||
442 | { | 443 | { |
443 | td->tune_range = DFLL_TUNE_LOW; | 444 | td->tune_range = DFLL_TUNE_LOW; |
444 | 445 | ||
445 | dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0); | 446 | dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0); |
446 | dfll_writel(td, td->soc->tune1, DFLL_TUNE1); | 447 | dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1); |
447 | dfll_wmb(td); | 448 | dfll_wmb(td); |
448 | 449 | ||
449 | if (td->soc->set_clock_trimmers_low) | 450 | if (td->soc->set_clock_trimmers_low) |
@@ -1449,7 +1450,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) | |||
1449 | } | 1450 | } |
1450 | v_max = dev_pm_opp_get_voltage(opp); | 1451 | v_max = dev_pm_opp_get_voltage(opp); |
1451 | 1452 | ||
1452 | v = td->soc->min_millivolts * 1000; | 1453 | v = td->soc->cvb->min_millivolts * 1000; |
1453 | lut = find_vdd_map_entry_exact(td, v); | 1454 | lut = find_vdd_map_entry_exact(td, v); |
1454 | if (lut < 0) | 1455 | if (lut < 0) |
1455 | goto out; | 1456 | goto out; |
@@ -1461,7 +1462,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) | |||
1461 | break; | 1462 | break; |
1462 | v_opp = dev_pm_opp_get_voltage(opp); | 1463 | v_opp = dev_pm_opp_get_voltage(opp); |
1463 | 1464 | ||
1464 | if (v_opp <= td->soc->min_millivolts * 1000) | 1465 | if (v_opp <= td->soc->cvb->min_millivolts * 1000) |
1465 | td->dvco_rate_min = dev_pm_opp_get_freq(opp); | 1466 | td->dvco_rate_min = dev_pm_opp_get_freq(opp); |
1466 | 1467 | ||
1467 | for (;;) { | 1468 | for (;;) { |
@@ -1490,7 +1491,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) | |||
1490 | 1491 | ||
1491 | if (!td->dvco_rate_min) | 1492 | if (!td->dvco_rate_min) |
1492 | dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n", | 1493 | dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n", |
1493 | td->soc->min_millivolts); | 1494 | td->soc->cvb->min_millivolts); |
1494 | else | 1495 | else |
1495 | ret = 0; | 1496 | ret = 0; |
1496 | 1497 | ||
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h index 2e4c0772a5dc..ed2ad888268f 100644 --- a/drivers/clk/tegra/clk-dfll.h +++ b/drivers/clk/tegra/clk-dfll.h | |||
@@ -24,22 +24,18 @@ | |||
24 | 24 | ||
25 | /** | 25 | /** |
26 | * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver | 26 | * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver |
27 | * @opp_dev: struct device * that holds the OPP table for the DFLL | 27 | * @dev: struct device * that holds the OPP table for the DFLL |
28 | * @min_millivolts: minimum voltage (in mV) that the DFLL can operate | 28 | * @max_freq: maximum frequency supported on this SoC |
29 | * @tune0_low: DFLL tuning register 0 (low voltage range) | 29 | * @cvb: CPU frequency table for this SoC |
30 | * @tune0_high: DFLL tuning register 0 (high voltage range) | 30 | * @init_clock_trimmers: callback to initialize clock trimmers |
31 | * @tune1: DFLL tuning register 1 | 31 | * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage |
32 | * @assert_dvco_reset: fn ptr to place the DVCO in reset | 32 | * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage |
33 | * @deassert_dvco_reset: fn ptr to release the DVCO reset | ||
34 | * @set_clock_trimmers_high: fn ptr to tune clock trimmers for high voltage | ||
35 | * @set_clock_trimmers_low: fn ptr to tune clock trimmers for low voltage | ||
36 | */ | 33 | */ |
37 | struct tegra_dfll_soc_data { | 34 | struct tegra_dfll_soc_data { |
38 | struct device *dev; | 35 | struct device *dev; |
39 | unsigned int min_millivolts; | 36 | unsigned long max_freq; |
40 | u32 tune0_low; | 37 | const struct cvb_table *cvb; |
41 | u32 tune0_high; | 38 | |
42 | u32 tune1; | ||
43 | void (*init_clock_trimmers)(void); | 39 | void (*init_clock_trimmers)(void); |
44 | void (*set_clock_trimmers_high)(void); | 40 | void (*set_clock_trimmers_high)(void); |
45 | void (*set_clock_trimmers_low)(void); | 41 | void (*set_clock_trimmers_low)(void); |
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 62ea38187b71..36c974916d4f 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h | |||
@@ -71,6 +71,7 @@ enum clk_id { | |||
71 | tegra_clk_disp2_8, | 71 | tegra_clk_disp2_8, |
72 | tegra_clk_dp2, | 72 | tegra_clk_dp2, |
73 | tegra_clk_dpaux, | 73 | tegra_clk_dpaux, |
74 | tegra_clk_dpaux1, | ||
74 | tegra_clk_dsialp, | 75 | tegra_clk_dsialp, |
75 | tegra_clk_dsia_mux, | 76 | tegra_clk_dsia_mux, |
76 | tegra_clk_dsiblp, | 77 | tegra_clk_dsiblp, |
@@ -306,6 +307,7 @@ enum clk_id { | |||
306 | tegra_clk_xusb_ss_div2, | 307 | tegra_clk_xusb_ss_div2, |
307 | tegra_clk_xusb_ssp_src, | 308 | tegra_clk_xusb_ssp_src, |
308 | tegra_clk_sclk_mux, | 309 | tegra_clk_sclk_mux, |
310 | tegra_clk_sor_safe, | ||
309 | tegra_clk_max, | 311 | tegra_clk_max, |
310 | }; | 312 | }; |
311 | 313 | ||
diff --git a/drivers/clk/tegra/clk-periph-fixed.c b/drivers/clk/tegra/clk-periph-fixed.c new file mode 100644 index 000000000000..c57dfb037b10 --- /dev/null +++ b/drivers/clk/tegra/clk-periph-fixed.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | |||
19 | #include "clk.h" | ||
20 | |||
21 | static inline struct tegra_clk_periph_fixed * | ||
22 | to_tegra_clk_periph_fixed(struct clk_hw *hw) | ||
23 | { | ||
24 | return container_of(hw, struct tegra_clk_periph_fixed, hw); | ||
25 | } | ||
26 | |||
27 | static int tegra_clk_periph_fixed_is_enabled(struct clk_hw *hw) | ||
28 | { | ||
29 | struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw); | ||
30 | u32 mask = 1 << (fixed->num % 32), value; | ||
31 | |||
32 | value = readl(fixed->base + fixed->regs->enb_reg); | ||
33 | if (value & mask) { | ||
34 | value = readl(fixed->base + fixed->regs->rst_reg); | ||
35 | if ((value & mask) == 0) | ||
36 | return 1; | ||
37 | } | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int tegra_clk_periph_fixed_enable(struct clk_hw *hw) | ||
43 | { | ||
44 | struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw); | ||
45 | u32 mask = 1 << (fixed->num % 32); | ||
46 | |||
47 | writel(mask, fixed->base + fixed->regs->enb_set_reg); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static void tegra_clk_periph_fixed_disable(struct clk_hw *hw) | ||
53 | { | ||
54 | struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw); | ||
55 | u32 mask = 1 << (fixed->num % 32); | ||
56 | |||
57 | writel(mask, fixed->base + fixed->regs->enb_clr_reg); | ||
58 | } | ||
59 | |||
60 | static unsigned long | ||
61 | tegra_clk_periph_fixed_recalc_rate(struct clk_hw *hw, | ||
62 | unsigned long parent_rate) | ||
63 | { | ||
64 | struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw); | ||
65 | unsigned long long rate; | ||
66 | |||
67 | rate = (unsigned long long)parent_rate * fixed->mul; | ||
68 | do_div(rate, fixed->div); | ||
69 | |||
70 | return (unsigned long)rate; | ||
71 | } | ||
72 | |||
73 | static const struct clk_ops tegra_clk_periph_fixed_ops = { | ||
74 | .is_enabled = tegra_clk_periph_fixed_is_enabled, | ||
75 | .enable = tegra_clk_periph_fixed_enable, | ||
76 | .disable = tegra_clk_periph_fixed_disable, | ||
77 | .recalc_rate = tegra_clk_periph_fixed_recalc_rate, | ||
78 | }; | ||
79 | |||
80 | struct clk *tegra_clk_register_periph_fixed(const char *name, | ||
81 | const char *parent, | ||
82 | unsigned long flags, | ||
83 | void __iomem *base, | ||
84 | unsigned int mul, | ||
85 | unsigned int div, | ||
86 | unsigned int num) | ||
87 | { | ||
88 | const struct tegra_clk_periph_regs *regs; | ||
89 | struct tegra_clk_periph_fixed *fixed; | ||
90 | struct clk_init_data init; | ||
91 | struct clk *clk; | ||
92 | |||
93 | regs = get_reg_bank(num); | ||
94 | if (!regs) | ||
95 | return ERR_PTR(-EINVAL); | ||
96 | |||
97 | fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); | ||
98 | if (!fixed) | ||
99 | return ERR_PTR(-ENOMEM); | ||
100 | |||
101 | init.name = name; | ||
102 | init.flags = flags; | ||
103 | init.parent_names = parent ? &parent : NULL; | ||
104 | init.num_parents = parent ? 1 : 0; | ||
105 | init.ops = &tegra_clk_periph_fixed_ops; | ||
106 | |||
107 | fixed->base = base; | ||
108 | fixed->regs = regs; | ||
109 | fixed->mul = mul; | ||
110 | fixed->div = div; | ||
111 | fixed->num = num; | ||
112 | |||
113 | fixed->hw.init = &init; | ||
114 | |||
115 | clk = clk_register(NULL, &fixed->hw); | ||
116 | if (IS_ERR(clk)) | ||
117 | kfree(fixed); | ||
118 | |||
119 | return clk; | ||
120 | } | ||
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index d28d6e95020f..88127828befe 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c | |||
@@ -134,7 +134,7 @@ struct clk *tegra_clk_register_periph_gate(const char *name, | |||
134 | struct tegra_clk_periph_gate *gate; | 134 | struct tegra_clk_periph_gate *gate; |
135 | struct clk *clk; | 135 | struct clk *clk; |
136 | struct clk_init_data init; | 136 | struct clk_init_data init; |
137 | struct tegra_clk_periph_regs *pregs; | 137 | const struct tegra_clk_periph_regs *pregs; |
138 | 138 | ||
139 | pregs = get_reg_bank(clk_num); | 139 | pregs = get_reg_bank(clk_num); |
140 | if (!pregs) | 140 | if (!pregs) |
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index ec5b6113b012..a17ca6d7f649 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c | |||
@@ -145,7 +145,7 @@ static struct clk *_tegra_clk_register_periph(const char *name, | |||
145 | { | 145 | { |
146 | struct clk *clk; | 146 | struct clk *clk; |
147 | struct clk_init_data init; | 147 | struct clk_init_data init; |
148 | struct tegra_clk_periph_regs *bank; | 148 | const struct tegra_clk_periph_regs *bank; |
149 | bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV); | 149 | bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV); |
150 | 150 | ||
151 | if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) { | 151 | if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) { |
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 6ac3f843e7ca..4e194ecc8d5e 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c | |||
@@ -2013,6 +2013,52 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, | |||
2013 | #endif | 2013 | #endif |
2014 | 2014 | ||
2015 | #if defined(CONFIG_ARCH_TEGRA_210_SOC) | 2015 | #if defined(CONFIG_ARCH_TEGRA_210_SOC) |
2016 | struct clk *tegra_clk_register_pllre_tegra210(const char *name, | ||
2017 | const char *parent_name, void __iomem *clk_base, | ||
2018 | void __iomem *pmc, unsigned long flags, | ||
2019 | struct tegra_clk_pll_params *pll_params, | ||
2020 | spinlock_t *lock, unsigned long parent_rate) | ||
2021 | { | ||
2022 | u32 val; | ||
2023 | struct tegra_clk_pll *pll; | ||
2024 | struct clk *clk; | ||
2025 | |||
2026 | pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); | ||
2027 | |||
2028 | if (pll_params->adjust_vco) | ||
2029 | pll_params->vco_min = pll_params->adjust_vco(pll_params, | ||
2030 | parent_rate); | ||
2031 | |||
2032 | pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); | ||
2033 | if (IS_ERR(pll)) | ||
2034 | return ERR_CAST(pll); | ||
2035 | |||
2036 | /* program minimum rate by default */ | ||
2037 | |||
2038 | val = pll_readl_base(pll); | ||
2039 | if (val & PLL_BASE_ENABLE) | ||
2040 | WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) & | ||
2041 | BIT(pll_params->iddq_bit_idx)); | ||
2042 | else { | ||
2043 | val = 0x4 << divm_shift(pll); | ||
2044 | val |= 0x41 << divn_shift(pll); | ||
2045 | pll_writel_base(val, pll); | ||
2046 | } | ||
2047 | |||
2048 | /* disable lock override */ | ||
2049 | |||
2050 | val = pll_readl_misc(pll); | ||
2051 | val &= ~BIT(29); | ||
2052 | pll_writel_misc(val, pll); | ||
2053 | |||
2054 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
2055 | &tegra_clk_pllre_ops); | ||
2056 | if (IS_ERR(clk)) | ||
2057 | kfree(pll); | ||
2058 | |||
2059 | return clk; | ||
2060 | } | ||
2061 | |||
2016 | static int clk_plle_tegra210_enable(struct clk_hw *hw) | 2062 | static int clk_plle_tegra210_enable(struct clk_hw *hw) |
2017 | { | 2063 | { |
2018 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 2064 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c index d64ec7a1b976..91c38f1666c1 100644 --- a/drivers/clk/tegra/clk-tegra-fixed.c +++ b/drivers/clk/tegra/clk-tegra-fixed.c | |||
@@ -107,4 +107,3 @@ void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks) | |||
107 | *dt_clk = clk; | 107 | *dt_clk = clk; |
108 | } | 108 | } |
109 | } | 109 | } |
110 | |||
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index ea2b9cbf9e70..29d04c663abf 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c | |||
@@ -803,7 +803,7 @@ static struct tegra_periph_init_data gate_clks[] = { | |||
803 | GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0), | 803 | GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0), |
804 | GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0), | 804 | GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0), |
805 | GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0), | 805 | GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0), |
806 | GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0), | 806 | GATE("mipi-cal", "clk72mhz", 56, 0, tegra_clk_mipi_cal, 0), |
807 | GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0), | 807 | GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0), |
808 | GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0), | 808 | GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0), |
809 | GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0), | 809 | GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0), |
@@ -821,7 +821,6 @@ static struct tegra_periph_init_data gate_clks[] = { | |||
821 | GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0), | 821 | GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0), |
822 | GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0), | 822 | GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0), |
823 | GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), | 823 | GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), |
824 | GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0), | ||
825 | GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), | 824 | GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), |
826 | GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0), | 825 | GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0), |
827 | GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0), | 826 | GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0), |
@@ -877,7 +876,7 @@ static void __init periph_clk_init(void __iomem *clk_base, | |||
877 | struct clk **dt_clk; | 876 | struct clk **dt_clk; |
878 | 877 | ||
879 | for (i = 0; i < ARRAY_SIZE(periph_clks); i++) { | 878 | for (i = 0; i < ARRAY_SIZE(periph_clks); i++) { |
880 | struct tegra_clk_periph_regs *bank; | 879 | const struct tegra_clk_periph_regs *bank; |
881 | struct tegra_periph_init_data *data; | 880 | struct tegra_periph_init_data *data; |
882 | 881 | ||
883 | data = periph_clks + i; | 882 | data = periph_clks + i; |
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index df47ec3169c3..b78054fac0a8 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c | |||
@@ -743,7 +743,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { | |||
743 | [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true }, | 743 | [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true }, |
744 | [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true }, | 744 | [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true }, |
745 | [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true }, | 745 | [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true }, |
746 | [tegra_clk_mipi_cal] = { .dt_id = TEGRA114_CLK_MIPI_CAL, .present = true }, | ||
747 | [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true }, | 746 | [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true }, |
748 | [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true }, | 747 | [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true }, |
749 | [tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true }, | 748 | [tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true }, |
@@ -1237,6 +1236,11 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base, | |||
1237 | &emc_lock); | 1236 | &emc_lock); |
1238 | clks[TEGRA114_CLK_MC] = clk; | 1237 | clks[TEGRA114_CLK_MC] = clk; |
1239 | 1238 | ||
1239 | clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base, | ||
1240 | CLK_SET_RATE_PARENT, 56, | ||
1241 | periph_clk_enb_refcnt); | ||
1242 | clks[TEGRA114_CLK_MIPI_CAL] = clk; | ||
1243 | |||
1240 | for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { | 1244 | for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { |
1241 | data = &tegra_periph_clk_list[i]; | 1245 | data = &tegra_periph_clk_list[i]; |
1242 | clk = tegra_clk_register_periph(data->name, | 1246 | clk = tegra_clk_register_periph(data->name, |
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index 61253330c12b..c205809ba580 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | |||
@@ -47,32 +47,32 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { | |||
47 | }, | 47 | }, |
48 | .speedo_scale = 100, | 48 | .speedo_scale = 100, |
49 | .voltage_scale = 1000, | 49 | .voltage_scale = 1000, |
50 | .cvb_table = { | 50 | .entries = { |
51 | {204000000UL, {1112619, -29295, 402} }, | 51 | { 204000000UL, { 1112619, -29295, 402 } }, |
52 | {306000000UL, {1150460, -30585, 402} }, | 52 | { 306000000UL, { 1150460, -30585, 402 } }, |
53 | {408000000UL, {1190122, -31865, 402} }, | 53 | { 408000000UL, { 1190122, -31865, 402 } }, |
54 | {510000000UL, {1231606, -33155, 402} }, | 54 | { 510000000UL, { 1231606, -33155, 402 } }, |
55 | {612000000UL, {1274912, -34435, 402} }, | 55 | { 612000000UL, { 1274912, -34435, 402 } }, |
56 | {714000000UL, {1320040, -35725, 402} }, | 56 | { 714000000UL, { 1320040, -35725, 402 } }, |
57 | {816000000UL, {1366990, -37005, 402} }, | 57 | { 816000000UL, { 1366990, -37005, 402 } }, |
58 | {918000000UL, {1415762, -38295, 402} }, | 58 | { 918000000UL, { 1415762, -38295, 402 } }, |
59 | {1020000000UL, {1466355, -39575, 402} }, | 59 | { 1020000000UL, { 1466355, -39575, 402 } }, |
60 | {1122000000UL, {1518771, -40865, 402} }, | 60 | { 1122000000UL, { 1518771, -40865, 402 } }, |
61 | {1224000000UL, {1573009, -42145, 402} }, | 61 | { 1224000000UL, { 1573009, -42145, 402 } }, |
62 | {1326000000UL, {1629068, -43435, 402} }, | 62 | { 1326000000UL, { 1629068, -43435, 402 } }, |
63 | {1428000000UL, {1686950, -44715, 402} }, | 63 | { 1428000000UL, { 1686950, -44715, 402 } }, |
64 | {1530000000UL, {1746653, -46005, 402} }, | 64 | { 1530000000UL, { 1746653, -46005, 402 } }, |
65 | {1632000000UL, {1808179, -47285, 402} }, | 65 | { 1632000000UL, { 1808179, -47285, 402 } }, |
66 | {1734000000UL, {1871526, -48575, 402} }, | 66 | { 1734000000UL, { 1871526, -48575, 402 } }, |
67 | {1836000000UL, {1936696, -49855, 402} }, | 67 | { 1836000000UL, { 1936696, -49855, 402 } }, |
68 | {1938000000UL, {2003687, -51145, 402} }, | 68 | { 1938000000UL, { 2003687, -51145, 402 } }, |
69 | {2014500000UL, {2054787, -52095, 402} }, | 69 | { 2014500000UL, { 2054787, -52095, 402 } }, |
70 | {2116500000UL, {2124957, -53385, 402} }, | 70 | { 2116500000UL, { 2124957, -53385, 402 } }, |
71 | {2218500000UL, {2196950, -54665, 402} }, | 71 | { 2218500000UL, { 2196950, -54665, 402 } }, |
72 | {2320500000UL, {2270765, -55955, 402} }, | 72 | { 2320500000UL, { 2270765, -55955, 402 } }, |
73 | {2422500000UL, {2346401, -57235, 402} }, | 73 | { 2422500000UL, { 2346401, -57235, 402 } }, |
74 | {2524500000UL, {2437299, -58535, 402} }, | 74 | { 2524500000UL, { 2437299, -58535, 402 } }, |
75 | {0, { 0, 0, 0} }, | 75 | { 0UL, { 0, 0, 0 } }, |
76 | }, | 76 | }, |
77 | .cpu_dfll_data = { | 77 | .cpu_dfll_data = { |
78 | .tune0_low = 0x005020ff, | 78 | .tune0_low = 0x005020ff, |
@@ -84,9 +84,8 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { | |||
84 | 84 | ||
85 | static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) | 85 | static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) |
86 | { | 86 | { |
87 | int process_id, speedo_id, speedo_value; | 87 | int process_id, speedo_id, speedo_value, err; |
88 | struct tegra_dfll_soc_data *soc; | 88 | struct tegra_dfll_soc_data *soc; |
89 | const struct cvb_table *cvb; | ||
90 | 89 | ||
91 | process_id = tegra_sku_info.cpu_process_id; | 90 | process_id = tegra_sku_info.cpu_process_id; |
92 | speedo_id = tegra_sku_info.cpu_speedo_id; | 91 | speedo_id = tegra_sku_info.cpu_speedo_id; |
@@ -108,23 +107,41 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) | |||
108 | return -ENODEV; | 107 | return -ENODEV; |
109 | } | 108 | } |
110 | 109 | ||
111 | cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables, | 110 | soc->max_freq = cpu_max_freq_table[speedo_id]; |
112 | ARRAY_SIZE(tegra124_cpu_cvb_tables), | 111 | |
113 | process_id, speedo_id, speedo_value, | 112 | soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables, |
114 | cpu_max_freq_table[speedo_id], | 113 | ARRAY_SIZE(tegra124_cpu_cvb_tables), |
115 | soc->dev); | 114 | process_id, speedo_id, speedo_value, |
116 | if (IS_ERR(cvb)) { | 115 | soc->max_freq); |
117 | dev_err(&pdev->dev, "couldn't build OPP table: %ld\n", | 116 | if (IS_ERR(soc->cvb)) { |
118 | PTR_ERR(cvb)); | 117 | dev_err(&pdev->dev, "couldn't add OPP table: %ld\n", |
119 | return PTR_ERR(cvb); | 118 | PTR_ERR(soc->cvb)); |
119 | return PTR_ERR(soc->cvb); | ||
120 | } | ||
121 | |||
122 | err = tegra_dfll_register(pdev, soc); | ||
123 | if (err < 0) { | ||
124 | tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); | ||
125 | return err; | ||
120 | } | 126 | } |
121 | 127 | ||
122 | soc->min_millivolts = cvb->min_millivolts; | 128 | platform_set_drvdata(pdev, soc); |
123 | soc->tune0_low = cvb->cpu_dfll_data.tune0_low; | 129 | |
124 | soc->tune0_high = cvb->cpu_dfll_data.tune0_high; | 130 | return 0; |
125 | soc->tune1 = cvb->cpu_dfll_data.tune1; | 131 | } |
132 | |||
133 | static int tegra124_dfll_fcpu_remove(struct platform_device *pdev) | ||
134 | { | ||
135 | struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev); | ||
136 | int err; | ||
137 | |||
138 | err = tegra_dfll_unregister(pdev); | ||
139 | if (err < 0) | ||
140 | dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err); | ||
141 | |||
142 | tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq); | ||
126 | 143 | ||
127 | return tegra_dfll_register(pdev, soc); | 144 | return 0; |
128 | } | 145 | } |
129 | 146 | ||
130 | static const struct of_device_id tegra124_dfll_fcpu_of_match[] = { | 147 | static const struct of_device_id tegra124_dfll_fcpu_of_match[] = { |
@@ -140,7 +157,7 @@ static const struct dev_pm_ops tegra124_dfll_pm_ops = { | |||
140 | 157 | ||
141 | static struct platform_driver tegra124_dfll_fcpu_driver = { | 158 | static struct platform_driver tegra124_dfll_fcpu_driver = { |
142 | .probe = tegra124_dfll_fcpu_probe, | 159 | .probe = tegra124_dfll_fcpu_probe, |
143 | .remove = tegra_dfll_unregister, | 160 | .remove = tegra124_dfll_fcpu_remove, |
144 | .driver = { | 161 | .driver = { |
145 | .name = "tegra124-dfll", | 162 | .name = "tegra124-dfll", |
146 | .of_match_table = tegra124_dfll_fcpu_of_match, | 163 | .of_match_table = tegra124_dfll_fcpu_of_match, |
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 1627258292d2..f4fbbf16a056 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c | |||
@@ -1155,6 +1155,10 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base, | |||
1155 | 1, 2); | 1155 | 1, 2); |
1156 | clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk; | 1156 | clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk; |
1157 | 1157 | ||
1158 | clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base, | ||
1159 | 1, 17, 181); | ||
1160 | clks[TEGRA124_CLK_DPAUX] = clk; | ||
1161 | |||
1158 | clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, | 1162 | clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, |
1159 | clk_base + PLLD_MISC, 30, 0, &pll_d_lock); | 1163 | clk_base + PLLD_MISC, 30, 0, &pll_d_lock); |
1160 | clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk; | 1164 | clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk; |
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 3d0edee1f9fe..b8551813ec43 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c | |||
@@ -92,6 +92,7 @@ | |||
92 | #define PLLE_AUX 0x48c | 92 | #define PLLE_AUX 0x48c |
93 | #define PLLRE_BASE 0x4c4 | 93 | #define PLLRE_BASE 0x4c4 |
94 | #define PLLRE_MISC0 0x4c8 | 94 | #define PLLRE_MISC0 0x4c8 |
95 | #define PLLRE_OUT1 0x4cc | ||
95 | #define PLLDP_BASE 0x590 | 96 | #define PLLDP_BASE 0x590 |
96 | #define PLLDP_MISC 0x594 | 97 | #define PLLDP_MISC 0x594 |
97 | 98 | ||
@@ -2150,6 +2151,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { | |||
2150 | [tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true }, | 2151 | [tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true }, |
2151 | [tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true }, | 2152 | [tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true }, |
2152 | [tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true }, | 2153 | [tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true }, |
2154 | [tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .present = true }, | ||
2153 | [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, | 2155 | [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, |
2154 | [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, | 2156 | [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, |
2155 | [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, | 2157 | [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, |
@@ -2461,6 +2463,18 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, | |||
2461 | 1, 2); | 2463 | 1, 2); |
2462 | clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; | 2464 | clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; |
2463 | 2465 | ||
2466 | clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base, | ||
2467 | 1, 17, 181); | ||
2468 | clks[TEGRA210_CLK_DPAUX] = clk; | ||
2469 | |||
2470 | clk = tegra_clk_register_periph_fixed("dpaux1", "pll_p", 0, clk_base, | ||
2471 | 1, 17, 207); | ||
2472 | clks[TEGRA210_CLK_DPAUX1] = clk; | ||
2473 | |||
2474 | clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base, | ||
2475 | 1, 17, 222); | ||
2476 | clks[TEGRA210_CLK_SOR_SAFE] = clk; | ||
2477 | |||
2464 | /* pll_d_dsi_out */ | 2478 | /* pll_d_dsi_out */ |
2465 | clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, | 2479 | clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, |
2466 | clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); | 2480 | clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); |
@@ -2640,8 +2654,10 @@ static void __init tegra210_pll_init(void __iomem *clk_base, | |||
2640 | clks[TEGRA210_CLK_PLL_D_OUT0] = clk; | 2654 | clks[TEGRA210_CLK_PLL_D_OUT0] = clk; |
2641 | 2655 | ||
2642 | /* PLLRE */ | 2656 | /* PLLRE */ |
2643 | clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, | 2657 | clk = tegra_clk_register_pllre_tegra210("pll_re_vco", "pll_ref", |
2644 | 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); | 2658 | clk_base, pmc, 0, |
2659 | &pll_re_vco_params, | ||
2660 | &pll_re_lock, pll_ref_freq); | ||
2645 | clk_register_clkdev(clk, "pll_re_vco", NULL); | 2661 | clk_register_clkdev(clk, "pll_re_vco", NULL); |
2646 | clks[TEGRA210_CLK_PLL_RE_VCO] = clk; | 2662 | clks[TEGRA210_CLK_PLL_RE_VCO] = clk; |
2647 | 2663 | ||
@@ -2651,6 +2667,15 @@ static void __init tegra210_pll_init(void __iomem *clk_base, | |||
2651 | clk_register_clkdev(clk, "pll_re_out", NULL); | 2667 | clk_register_clkdev(clk, "pll_re_out", NULL); |
2652 | clks[TEGRA210_CLK_PLL_RE_OUT] = clk; | 2668 | clks[TEGRA210_CLK_PLL_RE_OUT] = clk; |
2653 | 2669 | ||
2670 | clk = tegra_clk_register_divider("pll_re_out1_div", "pll_re_vco", | ||
2671 | clk_base + PLLRE_OUT1, 0, | ||
2672 | TEGRA_DIVIDER_ROUND_UP, | ||
2673 | 8, 8, 1, NULL); | ||
2674 | clk = tegra_clk_register_pll_out("pll_re_out1", "pll_re_out1_div", | ||
2675 | clk_base + PLLRE_OUT1, 1, 0, | ||
2676 | CLK_SET_RATE_PARENT, 0, NULL); | ||
2677 | clks[TEGRA210_CLK_PLL_RE_OUT1] = clk; | ||
2678 | |||
2654 | /* PLLE */ | 2679 | /* PLLE */ |
2655 | clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref", | 2680 | clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref", |
2656 | clk_base, 0, &pll_e_params, NULL); | 2681 | clk_base, 0, &pll_e_params, NULL); |
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 0478565cf292..9396f4930da7 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c | |||
@@ -339,11 +339,11 @@ static const struct pdiv_map pllu_p[] = { | |||
339 | }; | 339 | }; |
340 | 340 | ||
341 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { | 341 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { |
342 | { 12000000, 480000000, 960, 12, 1, 12 }, | 342 | { 12000000, 480000000, 960, 12, 2, 12 }, |
343 | { 13000000, 480000000, 960, 13, 1, 12 }, | 343 | { 13000000, 480000000, 960, 13, 2, 12 }, |
344 | { 16800000, 480000000, 400, 7, 1, 5 }, | 344 | { 16800000, 480000000, 400, 7, 2, 5 }, |
345 | { 19200000, 480000000, 200, 4, 1, 3 }, | 345 | { 19200000, 480000000, 200, 4, 2, 3 }, |
346 | { 26000000, 480000000, 960, 26, 1, 12 }, | 346 | { 26000000, 480000000, 960, 26, 2, 12 }, |
347 | { 0, 0, 0, 0, 0, 0 }, | 347 | { 0, 0, 0, 0, 0, 0 }, |
348 | }; | 348 | }; |
349 | 349 | ||
@@ -1372,6 +1372,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { | |||
1372 | { TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 }, | 1372 | { TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 }, |
1373 | { TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 }, | 1373 | { TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 }, |
1374 | { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 }, | 1374 | { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 }, |
1375 | { TEGRA30_CLK_PLL_C, TEGRA30_CLK_CLK_MAX, 600000000, 0 }, | ||
1375 | { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 }, | 1376 | { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 }, |
1376 | { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 }, | 1377 | { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 }, |
1377 | { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 }, | 1378 | { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 }, |
@@ -1379,6 +1380,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { | |||
1379 | { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 }, | 1380 | { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
1380 | { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, | 1381 | { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
1381 | { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, | 1382 | { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
1383 | { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 }, | ||
1382 | /* must be the last entry */ | 1384 | /* must be the last entry */ |
1383 | { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, | 1385 | { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, |
1384 | }; | 1386 | }; |
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index f60fe2e344ca..b2cdd9a235f4 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c | |||
@@ -84,7 +84,7 @@ static int (*special_reset_assert)(unsigned long); | |||
84 | static int (*special_reset_deassert)(unsigned long); | 84 | static int (*special_reset_deassert)(unsigned long); |
85 | static unsigned int num_special_reset; | 85 | static unsigned int num_special_reset; |
86 | 86 | ||
87 | static struct tegra_clk_periph_regs periph_regs[] = { | 87 | static const struct tegra_clk_periph_regs periph_regs[] = { |
88 | [0] = { | 88 | [0] = { |
89 | .enb_reg = CLK_OUT_ENB_L, | 89 | .enb_reg = CLK_OUT_ENB_L, |
90 | .enb_set_reg = CLK_OUT_ENB_SET_L, | 90 | .enb_set_reg = CLK_OUT_ENB_SET_L, |
@@ -182,7 +182,7 @@ static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, | |||
182 | return -EINVAL; | 182 | return -EINVAL; |
183 | } | 183 | } |
184 | 184 | ||
185 | struct tegra_clk_periph_regs *get_reg_bank(int clkid) | 185 | const struct tegra_clk_periph_regs *get_reg_bank(int clkid) |
186 | { | 186 | { |
187 | int reg_bank = clkid / 32; | 187 | int reg_bank = clkid / 32; |
188 | 188 | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 4dbcfaec576a..9421f0310999 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -386,6 +386,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, | |||
386 | struct tegra_clk_pll_params *pll_params, | 386 | struct tegra_clk_pll_params *pll_params, |
387 | spinlock_t *lock, unsigned long parent_rate); | 387 | spinlock_t *lock, unsigned long parent_rate); |
388 | 388 | ||
389 | struct clk *tegra_clk_register_pllre_tegra210(const char *name, | ||
390 | const char *parent_name, void __iomem *clk_base, | ||
391 | void __iomem *pmc, unsigned long flags, | ||
392 | struct tegra_clk_pll_params *pll_params, | ||
393 | spinlock_t *lock, unsigned long parent_rate); | ||
394 | |||
389 | struct clk *tegra_clk_register_plle_tegra114(const char *name, | 395 | struct clk *tegra_clk_register_plle_tegra114(const char *name, |
390 | const char *parent_name, | 396 | const char *parent_name, |
391 | void __iomem *clk_base, unsigned long flags, | 397 | void __iomem *clk_base, unsigned long flags, |
@@ -496,7 +502,7 @@ struct tegra_clk_periph_gate { | |||
496 | u8 flags; | 502 | u8 flags; |
497 | int clk_num; | 503 | int clk_num; |
498 | int *enable_refcnt; | 504 | int *enable_refcnt; |
499 | struct tegra_clk_periph_regs *regs; | 505 | const struct tegra_clk_periph_regs *regs; |
500 | }; | 506 | }; |
501 | 507 | ||
502 | #define to_clk_periph_gate(_hw) \ | 508 | #define to_clk_periph_gate(_hw) \ |
@@ -516,6 +522,23 @@ struct clk *tegra_clk_register_periph_gate(const char *name, | |||
516 | const char *parent_name, u8 gate_flags, void __iomem *clk_base, | 522 | const char *parent_name, u8 gate_flags, void __iomem *clk_base, |
517 | unsigned long flags, int clk_num, int *enable_refcnt); | 523 | unsigned long flags, int clk_num, int *enable_refcnt); |
518 | 524 | ||
525 | struct tegra_clk_periph_fixed { | ||
526 | struct clk_hw hw; | ||
527 | void __iomem *base; | ||
528 | const struct tegra_clk_periph_regs *regs; | ||
529 | unsigned int mul; | ||
530 | unsigned int div; | ||
531 | unsigned int num; | ||
532 | }; | ||
533 | |||
534 | struct clk *tegra_clk_register_periph_fixed(const char *name, | ||
535 | const char *parent, | ||
536 | unsigned long flags, | ||
537 | void __iomem *base, | ||
538 | unsigned int mul, | ||
539 | unsigned int div, | ||
540 | unsigned int num); | ||
541 | |||
519 | /** | 542 | /** |
520 | * struct clk-periph - peripheral clock | 543 | * struct clk-periph - peripheral clock |
521 | * | 544 | * |
@@ -716,7 +739,7 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl, | |||
716 | void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, | 739 | void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, |
717 | struct clk *clks[], int clk_max); | 740 | struct clk *clks[], int clk_max); |
718 | 741 | ||
719 | struct tegra_clk_periph_regs *get_reg_bank(int clkid); | 742 | const struct tegra_clk_periph_regs *get_reg_bank(int clkid); |
720 | struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); | 743 | struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); |
721 | 744 | ||
722 | struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); | 745 | struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); |
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c index 69c74eec3a4b..624115e82ff9 100644 --- a/drivers/clk/tegra/cvb.c +++ b/drivers/clk/tegra/cvb.c | |||
@@ -61,29 +61,28 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up) | |||
61 | return mv; | 61 | return mv; |
62 | } | 62 | } |
63 | 63 | ||
64 | static int build_opp_table(const struct cvb_table *d, | 64 | static int build_opp_table(struct device *dev, const struct cvb_table *table, |
65 | int speedo_value, | 65 | int speedo_value, unsigned long max_freq) |
66 | unsigned long max_freq, | ||
67 | struct device *opp_dev) | ||
68 | { | 66 | { |
67 | const struct rail_alignment *align = &table->alignment; | ||
69 | int i, ret, dfll_mv, min_mv, max_mv; | 68 | int i, ret, dfll_mv, min_mv, max_mv; |
70 | const struct cvb_table_freq_entry *table = NULL; | ||
71 | const struct rail_alignment *align = &d->alignment; | ||
72 | 69 | ||
73 | min_mv = round_voltage(d->min_millivolts, align, UP); | 70 | min_mv = round_voltage(table->min_millivolts, align, UP); |
74 | max_mv = round_voltage(d->max_millivolts, align, DOWN); | 71 | max_mv = round_voltage(table->max_millivolts, align, DOWN); |
75 | 72 | ||
76 | for (i = 0; i < MAX_DVFS_FREQS; i++) { | 73 | for (i = 0; i < MAX_DVFS_FREQS; i++) { |
77 | table = &d->cvb_table[i]; | 74 | const struct cvb_table_freq_entry *entry = &table->entries[i]; |
78 | if (!table->freq || (table->freq > max_freq)) | 75 | |
76 | if (!entry->freq || (entry->freq > max_freq)) | ||
79 | break; | 77 | break; |
80 | 78 | ||
81 | dfll_mv = get_cvb_voltage( | 79 | dfll_mv = get_cvb_voltage(speedo_value, table->speedo_scale, |
82 | speedo_value, d->speedo_scale, &table->coefficients); | 80 | &entry->coefficients); |
83 | dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align); | 81 | dfll_mv = round_cvb_voltage(dfll_mv, table->voltage_scale, |
82 | align); | ||
84 | dfll_mv = clamp(dfll_mv, min_mv, max_mv); | 83 | dfll_mv = clamp(dfll_mv, min_mv, max_mv); |
85 | 84 | ||
86 | ret = dev_pm_opp_add(opp_dev, table->freq, dfll_mv * 1000); | 85 | ret = dev_pm_opp_add(dev, entry->freq, dfll_mv * 1000); |
87 | if (ret) | 86 | if (ret) |
88 | return ret; | 87 | return ret; |
89 | } | 88 | } |
@@ -92,7 +91,7 @@ static int build_opp_table(const struct cvb_table *d, | |||
92 | } | 91 | } |
93 | 92 | ||
94 | /** | 93 | /** |
95 | * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables | 94 | * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables |
96 | * @cvb_tables: array of CVB tables | 95 | * @cvb_tables: array of CVB tables |
97 | * @sz: size of the previously mentioned array | 96 | * @sz: size of the previously mentioned array |
98 | * @process_id: process id of the HW module | 97 | * @process_id: process id of the HW module |
@@ -108,26 +107,42 @@ static int build_opp_table(const struct cvb_table *d, | |||
108 | * given @opp_dev. Returns a pointer to the struct cvb_table that matched | 107 | * given @opp_dev. Returns a pointer to the struct cvb_table that matched |
109 | * or an ERR_PTR on failure. | 108 | * or an ERR_PTR on failure. |
110 | */ | 109 | */ |
111 | const struct cvb_table *tegra_cvb_build_opp_table( | 110 | const struct cvb_table * |
112 | const struct cvb_table *cvb_tables, | 111 | tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables, |
113 | size_t sz, int process_id, | 112 | size_t count, int process_id, int speedo_id, |
114 | int speedo_id, int speedo_value, | 113 | int speedo_value, unsigned long max_freq) |
115 | unsigned long max_rate, | ||
116 | struct device *opp_dev) | ||
117 | { | 114 | { |
118 | int i, ret; | 115 | size_t i; |
116 | int ret; | ||
119 | 117 | ||
120 | for (i = 0; i < sz; i++) { | 118 | for (i = 0; i < count; i++) { |
121 | const struct cvb_table *d = &cvb_tables[i]; | 119 | const struct cvb_table *table = &tables[i]; |
122 | 120 | ||
123 | if (d->speedo_id != -1 && d->speedo_id != speedo_id) | 121 | if (table->speedo_id != -1 && table->speedo_id != speedo_id) |
124 | continue; | 122 | continue; |
125 | if (d->process_id != -1 && d->process_id != process_id) | 123 | |
124 | if (table->process_id != -1 && table->process_id != process_id) | ||
126 | continue; | 125 | continue; |
127 | 126 | ||
128 | ret = build_opp_table(d, speedo_value, max_rate, opp_dev); | 127 | ret = build_opp_table(dev, table, speedo_value, max_freq); |
129 | return ret ? ERR_PTR(ret) : d; | 128 | return ret ? ERR_PTR(ret) : table; |
130 | } | 129 | } |
131 | 130 | ||
132 | return ERR_PTR(-EINVAL); | 131 | return ERR_PTR(-EINVAL); |
133 | } | 132 | } |
133 | |||
134 | void tegra_cvb_remove_opp_table(struct device *dev, | ||
135 | const struct cvb_table *table, | ||
136 | unsigned long max_freq) | ||
137 | { | ||
138 | unsigned int i; | ||
139 | |||
140 | for (i = 0; i < MAX_DVFS_FREQS; i++) { | ||
141 | const struct cvb_table_freq_entry *entry = &table->entries[i]; | ||
142 | |||
143 | if (!entry->freq || (entry->freq > max_freq)) | ||
144 | break; | ||
145 | |||
146 | dev_pm_opp_remove(dev, entry->freq); | ||
147 | } | ||
148 | } | ||
diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h index f62cdc4f4234..c1f077993b2a 100644 --- a/drivers/clk/tegra/cvb.h +++ b/drivers/clk/tegra/cvb.h | |||
@@ -53,15 +53,16 @@ struct cvb_table { | |||
53 | 53 | ||
54 | int speedo_scale; | 54 | int speedo_scale; |
55 | int voltage_scale; | 55 | int voltage_scale; |
56 | struct cvb_table_freq_entry cvb_table[MAX_DVFS_FREQS]; | 56 | struct cvb_table_freq_entry entries[MAX_DVFS_FREQS]; |
57 | struct cvb_cpu_dfll_data cpu_dfll_data; | 57 | struct cvb_cpu_dfll_data cpu_dfll_data; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | const struct cvb_table *tegra_cvb_build_opp_table( | 60 | const struct cvb_table * |
61 | const struct cvb_table *cvb_tables, | 61 | tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables, |
62 | size_t sz, int process_id, | 62 | size_t count, int process_id, int speedo_id, |
63 | int speedo_id, int speedo_value, | 63 | int speedo_value, unsigned long max_freq); |
64 | unsigned long max_rate, | 64 | void tegra_cvb_remove_opp_table(struct device *dev, |
65 | struct device *opp_dev); | 65 | const struct cvb_table *table, |
66 | unsigned long max_freq); | ||
66 | 67 | ||
67 | #endif | 68 | #endif |
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index 59ce2fa2c104..294bc03ec067 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c | |||
@@ -210,6 +210,7 @@ static struct ti_dt_clk omap54xx_clks[] = { | |||
210 | DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), | 210 | DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), |
211 | DT_CLK("omap_wdt", "ick", "dummy_ck"), | 211 | DT_CLK("omap_wdt", "ick", "dummy_ck"), |
212 | DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), | 212 | DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), |
213 | DT_CLK(NULL, "sys_clkin_ck", "sys_clkin"), | ||
213 | DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin"), | 214 | DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin"), |
214 | DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin"), | 215 | DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin"), |
215 | DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin"), | 216 | DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin"), |
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index 6b5a309d9939..bfa17d33ef3b 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c | |||
@@ -289,6 +289,7 @@ static struct ti_dt_clk dra7xx_clks[] = { | |||
289 | DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), | 289 | DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), |
290 | DT_CLK("omap_wdt", "ick", "dummy_ck"), | 290 | DT_CLK("omap_wdt", "ick", "dummy_ck"), |
291 | DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), | 291 | DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), |
292 | DT_CLK(NULL, "sys_clkin_ck", "timer_sys_clk_div"), | ||
292 | DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"), | 293 | DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"), |
293 | DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"), | 294 | DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"), |
294 | DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"), | 295 | DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"), |
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 2e14dfb588f4..c77333230bdf 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c | |||
@@ -265,6 +265,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) | |||
265 | 265 | ||
266 | /* Get configuration for the ATL instances */ | 266 | /* Get configuration for the ATL instances */ |
267 | snprintf(prop, sizeof(prop), "atl%u", i); | 267 | snprintf(prop, sizeof(prop), "atl%u", i); |
268 | of_node_get(node); | ||
268 | cfg_node = of_find_node_by_name(node, prop); | 269 | cfg_node = of_find_node_by_name(node, prop); |
269 | if (cfg_node) { | 270 | if (cfg_node) { |
270 | ret = of_property_read_u32(cfg_node, "bws", | 271 | ret = of_property_read_u32(cfg_node, "bws", |
@@ -278,6 +279,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) | |||
278 | atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i), | 279 | atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i), |
279 | cdesc->aws); | 280 | cdesc->aws); |
280 | } | 281 | } |
282 | of_node_put(cfg_node); | ||
281 | } | 283 | } |
282 | 284 | ||
283 | cdesc->probed = true; | 285 | cdesc->probed = true; |
diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c index 1ddc288fce4e..c6ae563801d7 100644 --- a/drivers/clk/ti/clkt_dflt.c +++ b/drivers/clk/ti/clkt_dflt.c | |||
@@ -222,7 +222,7 @@ int omap2_dflt_clk_enable(struct clk_hw *hw) | |||
222 | } | 222 | } |
223 | } | 223 | } |
224 | 224 | ||
225 | if (unlikely(IS_ERR(clk->enable_reg))) { | 225 | if (IS_ERR(clk->enable_reg)) { |
226 | pr_err("%s: %s missing enable_reg\n", __func__, | 226 | pr_err("%s: %s missing enable_reg\n", __func__, |
227 | clk_hw_get_name(hw)); | 227 | clk_hw_get_name(hw)); |
228 | ret = -EINVAL; | 228 | ret = -EINVAL; |
diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c index 032c658a5f5e..b919fdfe8256 100644 --- a/drivers/clk/ti/clkt_dpll.c +++ b/drivers/clk/ti/clkt_dpll.c | |||
@@ -301,6 +301,9 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, | |||
301 | 301 | ||
302 | dd = clk->dpll_data; | 302 | dd = clk->dpll_data; |
303 | 303 | ||
304 | if (dd->max_rate && target_rate > dd->max_rate) | ||
305 | target_rate = dd->max_rate; | ||
306 | |||
304 | ref_rate = clk_hw_get_rate(dd->clk_ref); | 307 | ref_rate = clk_hw_get_rate(dd->clk_ref); |
305 | clk_name = clk_hw_get_name(hw); | 308 | clk_name = clk_hw_get_name(hw); |
306 | pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", | 309 | pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n", |
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 3bc9959f71c3..9fc8754a6e61 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c | |||
@@ -655,6 +655,7 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node) | |||
655 | .max_multiplier = 2047, | 655 | .max_multiplier = 2047, |
656 | .max_divider = 128, | 656 | .max_divider = 128, |
657 | .min_divider = 1, | 657 | .min_divider = 1, |
658 | .max_rate = 1000000000, | ||
658 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 659 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
659 | }; | 660 | }; |
660 | 661 | ||
@@ -674,6 +675,7 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node) | |||
674 | .max_divider = 256, | 675 | .max_divider = 256, |
675 | .min_divider = 2, | 676 | .min_divider = 2, |
676 | .flags = DPLL_J_TYPE, | 677 | .flags = DPLL_J_TYPE, |
678 | .max_rate = 2000000000, | ||
677 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 679 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
678 | }; | 680 | }; |
679 | 681 | ||
@@ -692,6 +694,7 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node) | |||
692 | .max_multiplier = 2047, | 694 | .max_multiplier = 2047, |
693 | .max_divider = 128, | 695 | .max_divider = 128, |
694 | .min_divider = 1, | 696 | .min_divider = 1, |
697 | .max_rate = 2000000000, | ||
695 | .flags = DPLL_J_TYPE, | 698 | .flags = DPLL_J_TYPE, |
696 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 699 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
697 | }; | 700 | }; |
@@ -712,6 +715,7 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node) | |||
712 | .max_multiplier = 2047, | 715 | .max_multiplier = 2047, |
713 | .max_divider = 128, | 716 | .max_divider = 128, |
714 | .min_divider = 1, | 717 | .min_divider = 1, |
718 | .max_rate = 1000000000, | ||
715 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 719 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
716 | }; | 720 | }; |
717 | 721 | ||
@@ -729,6 +733,7 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node) | |||
729 | .max_multiplier = 2047, | 733 | .max_multiplier = 2047, |
730 | .max_divider = 128, | 734 | .max_divider = 128, |
731 | .min_divider = 1, | 735 | .min_divider = 1, |
736 | .max_rate = 1000000000, | ||
732 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 737 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
733 | }; | 738 | }; |
734 | 739 | ||
diff --git a/drivers/clk/zte/clk-zx296702.c b/drivers/clk/zte/clk-zx296702.c index ebd20d852e73..76e967c19775 100644 --- a/drivers/clk/zte/clk-zx296702.c +++ b/drivers/clk/zte/clk-zx296702.c | |||
@@ -234,8 +234,7 @@ static void __init zx296702_top_clocks_init(struct device_node *np) | |||
234 | WARN_ON(!topcrm_base); | 234 | WARN_ON(!topcrm_base); |
235 | 235 | ||
236 | clk[ZX296702_OSC] = | 236 | clk[ZX296702_OSC] = |
237 | clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT, | 237 | clk_register_fixed_rate(NULL, "osc", NULL, 0, 30000000); |
238 | 30000000); | ||
239 | clk[ZX296702_PLL_A9] = | 238 | clk[ZX296702_PLL_A9] = |
240 | clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base | 239 | clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base |
241 | + 0x01c, pll_a9_config, | 240 | + 0x01c, pll_a9_config, |
diff --git a/include/dt-bindings/clock/axis,artpec6-clkctrl.h b/include/dt-bindings/clock/axis,artpec6-clkctrl.h new file mode 100644 index 000000000000..f9f04dccc996 --- /dev/null +++ b/include/dt-bindings/clock/axis,artpec6-clkctrl.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * ARTPEC-6 clock controller indexes | ||
3 | * | ||
4 | * Copyright 2016 Axis Comunications AB. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef DT_BINDINGS_CLK_ARTPEC6_CLKCTRL_H | ||
12 | #define DT_BINDINGS_CLK_ARTPEC6_CLKCTRL_H | ||
13 | |||
14 | #define ARTPEC6_CLK_CPU 0 | ||
15 | #define ARTPEC6_CLK_CPU_PERIPH 1 | ||
16 | #define ARTPEC6_CLK_NAND_CLKA 2 | ||
17 | #define ARTPEC6_CLK_NAND_CLKB 3 | ||
18 | #define ARTPEC6_CLK_ETH_ACLK 4 | ||
19 | #define ARTPEC6_CLK_DMA_ACLK 5 | ||
20 | #define ARTPEC6_CLK_PTP_REF 6 | ||
21 | #define ARTPEC6_CLK_SD_PCLK 7 | ||
22 | #define ARTPEC6_CLK_SD_IMCLK 8 | ||
23 | #define ARTPEC6_CLK_I2S_HST 9 | ||
24 | #define ARTPEC6_CLK_I2S0_CLK 10 | ||
25 | #define ARTPEC6_CLK_I2S1_CLK 11 | ||
26 | #define ARTPEC6_CLK_UART_PCLK 12 | ||
27 | #define ARTPEC6_CLK_UART_REFCLK 13 | ||
28 | #define ARTPEC6_CLK_I2C 14 | ||
29 | #define ARTPEC6_CLK_SPI_PCLK 15 | ||
30 | #define ARTPEC6_CLK_SPI_SSPCLK 16 | ||
31 | #define ARTPEC6_CLK_SYS_TIMER 17 | ||
32 | #define ARTPEC6_CLK_FRACDIV_IN 18 | ||
33 | #define ARTPEC6_CLK_DBG_PCLK 19 | ||
34 | |||
35 | /* This must be the highest clock index plus one. */ | ||
36 | #define ARTPEC6_CLK_NUMCLOCKS 20 | ||
37 | |||
38 | #endif | ||
diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h index 61f1d20c2a67..360e00cefd35 100644 --- a/include/dt-bindings/clock/bcm2835.h +++ b/include/dt-bindings/clock/bcm2835.h | |||
@@ -44,5 +44,23 @@ | |||
44 | #define BCM2835_CLOCK_EMMC 28 | 44 | #define BCM2835_CLOCK_EMMC 28 |
45 | #define BCM2835_CLOCK_PERI_IMAGE 29 | 45 | #define BCM2835_CLOCK_PERI_IMAGE 29 |
46 | #define BCM2835_CLOCK_PWM 30 | 46 | #define BCM2835_CLOCK_PWM 30 |
47 | #define BCM2835_CLOCK_PCM 31 | ||
47 | 48 | ||
48 | #define BCM2835_CLOCK_COUNT 31 | 49 | #define BCM2835_PLLA_DSI0 32 |
50 | #define BCM2835_PLLA_CCP2 33 | ||
51 | #define BCM2835_PLLD_DSI0 34 | ||
52 | #define BCM2835_PLLD_DSI1 35 | ||
53 | |||
54 | #define BCM2835_CLOCK_AVEO 36 | ||
55 | #define BCM2835_CLOCK_DFT 37 | ||
56 | #define BCM2835_CLOCK_GP0 38 | ||
57 | #define BCM2835_CLOCK_GP1 39 | ||
58 | #define BCM2835_CLOCK_GP2 40 | ||
59 | #define BCM2835_CLOCK_SLIM 41 | ||
60 | #define BCM2835_CLOCK_SMI 42 | ||
61 | #define BCM2835_CLOCK_TEC 43 | ||
62 | #define BCM2835_CLOCK_DPI 44 | ||
63 | #define BCM2835_CLOCK_CAM0 45 | ||
64 | #define BCM2835_CLOCK_CAM1 46 | ||
65 | #define BCM2835_CLOCK_DSI0E 47 | ||
66 | #define BCM2835_CLOCK_DSI1E 48 | ||
diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h index 7699ee9c16c0..17ab8394bec7 100644 --- a/include/dt-bindings/clock/exynos5420.h +++ b/include/dt-bindings/clock/exynos5420.h | |||
@@ -217,8 +217,30 @@ | |||
217 | 217 | ||
218 | /* divider clocks */ | 218 | /* divider clocks */ |
219 | #define CLK_DOUT_PIXEL 768 | 219 | #define CLK_DOUT_PIXEL 768 |
220 | #define CLK_DOUT_ACLK400_WCORE 769 | ||
221 | #define CLK_DOUT_ACLK400_ISP 770 | ||
222 | #define CLK_DOUT_ACLK400_MSCL 771 | ||
223 | #define CLK_DOUT_ACLK200 772 | ||
224 | #define CLK_DOUT_ACLK200_FSYS2 773 | ||
225 | #define CLK_DOUT_ACLK100_NOC 774 | ||
226 | #define CLK_DOUT_PCLK200_FSYS 775 | ||
227 | #define CLK_DOUT_ACLK200_FSYS 776 | ||
228 | #define CLK_DOUT_ACLK333_432_GSCL 777 | ||
229 | #define CLK_DOUT_ACLK333_432_ISP 778 | ||
230 | #define CLK_DOUT_ACLK66 779 | ||
231 | #define CLK_DOUT_ACLK333_432_ISP0 780 | ||
232 | #define CLK_DOUT_ACLK266 781 | ||
233 | #define CLK_DOUT_ACLK166 782 | ||
234 | #define CLK_DOUT_ACLK333 783 | ||
235 | #define CLK_DOUT_ACLK333_G2D 784 | ||
236 | #define CLK_DOUT_ACLK266_G2D 785 | ||
237 | #define CLK_DOUT_ACLK_G3D 786 | ||
238 | #define CLK_DOUT_ACLK300_JPEG 787 | ||
239 | #define CLK_DOUT_ACLK300_DISP1 788 | ||
240 | #define CLK_DOUT_ACLK300_GSCL 789 | ||
241 | #define CLK_DOUT_ACLK400_DISP1 790 | ||
220 | 242 | ||
221 | /* must be greater than maximal clock id */ | 243 | /* must be greater than maximal clock id */ |
222 | #define CLK_NR_CLKS 769 | 244 | #define CLK_NR_CLKS 791 |
223 | 245 | ||
224 | #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5420_H */ | 246 | #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5420_H */ |
diff --git a/include/dt-bindings/clock/hi3519-clock.h b/include/dt-bindings/clock/hi3519-clock.h new file mode 100644 index 000000000000..14f4d2184e5a --- /dev/null +++ b/include/dt-bindings/clock/hi3519-clock.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 HiSilicon Technologies Co., Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #ifndef __DTS_HI3519_CLOCK_H | ||
19 | #define __DTS_HI3519_CLOCK_H | ||
20 | |||
21 | #define HI3519_FMC_CLK 1 | ||
22 | #define HI3519_SPI0_CLK 2 | ||
23 | #define HI3519_SPI1_CLK 3 | ||
24 | #define HI3519_SPI2_CLK 4 | ||
25 | #define HI3519_UART0_CLK 5 | ||
26 | #define HI3519_UART1_CLK 6 | ||
27 | #define HI3519_UART2_CLK 7 | ||
28 | #define HI3519_UART3_CLK 8 | ||
29 | #define HI3519_UART4_CLK 9 | ||
30 | #define HI3519_PWM_CLK 10 | ||
31 | #define HI3519_DMA_CLK 11 | ||
32 | #define HI3519_IR_CLK 12 | ||
33 | #define HI3519_ETH_PHY_CLK 13 | ||
34 | #define HI3519_ETH_MAC_CLK 14 | ||
35 | #define HI3519_ETH_MACIF_CLK 15 | ||
36 | #define HI3519_USB2_BUS_CLK 16 | ||
37 | #define HI3519_USB2_PORT_CLK 17 | ||
38 | #define HI3519_USB3_CLK 18 | ||
39 | |||
40 | #endif /* __DTS_HI3519_CLOCK_H */ | ||
diff --git a/include/dt-bindings/clock/imx7d-clock.h b/include/dt-bindings/clock/imx7d-clock.h index edca8985c50e..1183347c383f 100644 --- a/include/dt-bindings/clock/imx7d-clock.h +++ b/include/dt-bindings/clock/imx7d-clock.h | |||
@@ -448,5 +448,6 @@ | |||
448 | #define IMX7D_PLL_DRAM_TEST_DIV 435 | 448 | #define IMX7D_PLL_DRAM_TEST_DIV 435 |
449 | #define IMX7D_ADC_ROOT_CLK 436 | 449 | #define IMX7D_ADC_ROOT_CLK 436 |
450 | #define IMX7D_CLK_ARM 437 | 450 | #define IMX7D_CLK_ARM 437 |
451 | #define IMX7D_CLK_END 438 | 451 | #define IMX7D_CKIL 438 |
452 | #define IMX7D_CLK_END 439 | ||
452 | #endif /* __DT_BINDINGS_CLOCK_IMX7D_H */ | 453 | #endif /* __DT_BINDINGS_CLOCK_IMX7D_H */ |
diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index 0a05b0d36ae7..bd3530e56d46 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h | |||
@@ -346,7 +346,7 @@ | |||
346 | #define TEGRA210_CLK_PLL_P_OUT_HSIO 316 | 346 | #define TEGRA210_CLK_PLL_P_OUT_HSIO 316 |
347 | #define TEGRA210_CLK_PLL_P_OUT_XUSB 317 | 347 | #define TEGRA210_CLK_PLL_P_OUT_XUSB 317 |
348 | #define TEGRA210_CLK_XUSB_SSP_SRC 318 | 348 | #define TEGRA210_CLK_XUSB_SSP_SRC 318 |
349 | /* 319 */ | 349 | #define TEGRA210_CLK_PLL_RE_OUT1 319 |
350 | /* 320 */ | 350 | /* 320 */ |
351 | /* 321 */ | 351 | /* 321 */ |
352 | /* 322 */ | 352 | /* 322 */ |
diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h index 56c16aaea112..45997750c8a0 100644 --- a/include/dt-bindings/clock/vf610-clock.h +++ b/include/dt-bindings/clock/vf610-clock.h | |||
@@ -194,7 +194,11 @@ | |||
194 | #define VF610_PLL7_BYPASS 181 | 194 | #define VF610_PLL7_BYPASS 181 |
195 | #define VF610_CLK_SNVS 182 | 195 | #define VF610_CLK_SNVS 182 |
196 | #define VF610_CLK_DAP 183 | 196 | #define VF610_CLK_DAP 183 |
197 | #define VF610_CLK_OCOTP 184 | 197 | #define VF610_CLK_OCOTP 184 |
198 | #define VF610_CLK_END 185 | 198 | #define VF610_CLK_DDRMC 185 |
199 | #define VF610_CLK_WKPU 186 | ||
200 | #define VF610_CLK_TCON0 187 | ||
201 | #define VF610_CLK_TCON1 188 | ||
202 | #define VF610_CLK_END 189 | ||
199 | 203 | ||
200 | #endif /* __DT_BINDINGS_CLOCK_VF610_H */ | 204 | #endif /* __DT_BINDINGS_CLOCK_VF610_H */ |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index da95258127aa..0c72204c75fc 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ | 32 | #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ |
33 | #define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ | 33 | #define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ |
34 | #define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ | 34 | #define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ |
35 | #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ | ||
35 | 36 | ||
36 | struct clk; | 37 | struct clk; |
37 | struct clk_hw; | 38 | struct clk_hw; |
@@ -282,10 +283,17 @@ extern const struct clk_ops clk_fixed_rate_ops; | |||
282 | struct clk *clk_register_fixed_rate(struct device *dev, const char *name, | 283 | struct clk *clk_register_fixed_rate(struct device *dev, const char *name, |
283 | const char *parent_name, unsigned long flags, | 284 | const char *parent_name, unsigned long flags, |
284 | unsigned long fixed_rate); | 285 | unsigned long fixed_rate); |
286 | struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name, | ||
287 | const char *parent_name, unsigned long flags, | ||
288 | unsigned long fixed_rate); | ||
285 | struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, | 289 | struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, |
286 | const char *name, const char *parent_name, unsigned long flags, | 290 | const char *name, const char *parent_name, unsigned long flags, |
287 | unsigned long fixed_rate, unsigned long fixed_accuracy); | 291 | unsigned long fixed_rate, unsigned long fixed_accuracy); |
288 | void clk_unregister_fixed_rate(struct clk *clk); | 292 | void clk_unregister_fixed_rate(struct clk *clk); |
293 | struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, | ||
294 | const char *name, const char *parent_name, unsigned long flags, | ||
295 | unsigned long fixed_rate, unsigned long fixed_accuracy); | ||
296 | |||
289 | void of_fixed_clk_setup(struct device_node *np); | 297 | void of_fixed_clk_setup(struct device_node *np); |
290 | 298 | ||
291 | /** | 299 | /** |
@@ -326,7 +334,12 @@ struct clk *clk_register_gate(struct device *dev, const char *name, | |||
326 | const char *parent_name, unsigned long flags, | 334 | const char *parent_name, unsigned long flags, |
327 | void __iomem *reg, u8 bit_idx, | 335 | void __iomem *reg, u8 bit_idx, |
328 | u8 clk_gate_flags, spinlock_t *lock); | 336 | u8 clk_gate_flags, spinlock_t *lock); |
337 | struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, | ||
338 | const char *parent_name, unsigned long flags, | ||
339 | void __iomem *reg, u8 bit_idx, | ||
340 | u8 clk_gate_flags, spinlock_t *lock); | ||
329 | void clk_unregister_gate(struct clk *clk); | 341 | void clk_unregister_gate(struct clk *clk); |
342 | void clk_hw_unregister_gate(struct clk_hw *hw); | ||
330 | 343 | ||
331 | struct clk_div_table { | 344 | struct clk_div_table { |
332 | unsigned int val; | 345 | unsigned int val; |
@@ -407,12 +420,22 @@ struct clk *clk_register_divider(struct device *dev, const char *name, | |||
407 | const char *parent_name, unsigned long flags, | 420 | const char *parent_name, unsigned long flags, |
408 | void __iomem *reg, u8 shift, u8 width, | 421 | void __iomem *reg, u8 shift, u8 width, |
409 | u8 clk_divider_flags, spinlock_t *lock); | 422 | u8 clk_divider_flags, spinlock_t *lock); |
423 | struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, | ||
424 | const char *parent_name, unsigned long flags, | ||
425 | void __iomem *reg, u8 shift, u8 width, | ||
426 | u8 clk_divider_flags, spinlock_t *lock); | ||
410 | struct clk *clk_register_divider_table(struct device *dev, const char *name, | 427 | struct clk *clk_register_divider_table(struct device *dev, const char *name, |
411 | const char *parent_name, unsigned long flags, | 428 | const char *parent_name, unsigned long flags, |
412 | void __iomem *reg, u8 shift, u8 width, | 429 | void __iomem *reg, u8 shift, u8 width, |
413 | u8 clk_divider_flags, const struct clk_div_table *table, | 430 | u8 clk_divider_flags, const struct clk_div_table *table, |
414 | spinlock_t *lock); | 431 | spinlock_t *lock); |
432 | struct clk_hw *clk_hw_register_divider_table(struct device *dev, | ||
433 | const char *name, const char *parent_name, unsigned long flags, | ||
434 | void __iomem *reg, u8 shift, u8 width, | ||
435 | u8 clk_divider_flags, const struct clk_div_table *table, | ||
436 | spinlock_t *lock); | ||
415 | void clk_unregister_divider(struct clk *clk); | 437 | void clk_unregister_divider(struct clk *clk); |
438 | void clk_hw_unregister_divider(struct clk_hw *hw); | ||
416 | 439 | ||
417 | /** | 440 | /** |
418 | * struct clk_mux - multiplexer clock | 441 | * struct clk_mux - multiplexer clock |
@@ -463,14 +486,25 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
463 | unsigned long flags, | 486 | unsigned long flags, |
464 | void __iomem *reg, u8 shift, u8 width, | 487 | void __iomem *reg, u8 shift, u8 width, |
465 | u8 clk_mux_flags, spinlock_t *lock); | 488 | u8 clk_mux_flags, spinlock_t *lock); |
489 | struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name, | ||
490 | const char * const *parent_names, u8 num_parents, | ||
491 | unsigned long flags, | ||
492 | void __iomem *reg, u8 shift, u8 width, | ||
493 | u8 clk_mux_flags, spinlock_t *lock); | ||
466 | 494 | ||
467 | struct clk *clk_register_mux_table(struct device *dev, const char *name, | 495 | struct clk *clk_register_mux_table(struct device *dev, const char *name, |
468 | const char * const *parent_names, u8 num_parents, | 496 | const char * const *parent_names, u8 num_parents, |
469 | unsigned long flags, | 497 | unsigned long flags, |
470 | void __iomem *reg, u8 shift, u32 mask, | 498 | void __iomem *reg, u8 shift, u32 mask, |
471 | u8 clk_mux_flags, u32 *table, spinlock_t *lock); | 499 | u8 clk_mux_flags, u32 *table, spinlock_t *lock); |
500 | struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, | ||
501 | const char * const *parent_names, u8 num_parents, | ||
502 | unsigned long flags, | ||
503 | void __iomem *reg, u8 shift, u32 mask, | ||
504 | u8 clk_mux_flags, u32 *table, spinlock_t *lock); | ||
472 | 505 | ||
473 | void clk_unregister_mux(struct clk *clk); | 506 | void clk_unregister_mux(struct clk *clk); |
507 | void clk_hw_unregister_mux(struct clk_hw *hw); | ||
474 | 508 | ||
475 | void of_fixed_factor_clk_setup(struct device_node *node); | 509 | void of_fixed_factor_clk_setup(struct device_node *node); |
476 | 510 | ||
@@ -499,6 +533,10 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | |||
499 | const char *parent_name, unsigned long flags, | 533 | const char *parent_name, unsigned long flags, |
500 | unsigned int mult, unsigned int div); | 534 | unsigned int mult, unsigned int div); |
501 | void clk_unregister_fixed_factor(struct clk *clk); | 535 | void clk_unregister_fixed_factor(struct clk *clk); |
536 | struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, | ||
537 | const char *name, const char *parent_name, unsigned long flags, | ||
538 | unsigned int mult, unsigned int div); | ||
539 | void clk_hw_unregister_fixed_factor(struct clk_hw *hw); | ||
502 | 540 | ||
503 | /** | 541 | /** |
504 | * struct clk_fractional_divider - adjustable fractional divider clock | 542 | * struct clk_fractional_divider - adjustable fractional divider clock |
@@ -533,6 +571,11 @@ struct clk *clk_register_fractional_divider(struct device *dev, | |||
533 | const char *name, const char *parent_name, unsigned long flags, | 571 | const char *name, const char *parent_name, unsigned long flags, |
534 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, | 572 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, |
535 | u8 clk_divider_flags, spinlock_t *lock); | 573 | u8 clk_divider_flags, spinlock_t *lock); |
574 | struct clk_hw *clk_hw_register_fractional_divider(struct device *dev, | ||
575 | const char *name, const char *parent_name, unsigned long flags, | ||
576 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, | ||
577 | u8 clk_divider_flags, spinlock_t *lock); | ||
578 | void clk_hw_unregister_fractional_divider(struct clk_hw *hw); | ||
536 | 579 | ||
537 | /** | 580 | /** |
538 | * struct clk_multiplier - adjustable multiplier clock | 581 | * struct clk_multiplier - adjustable multiplier clock |
@@ -603,6 +646,14 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
603 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, | 646 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, |
604 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | 647 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, |
605 | unsigned long flags); | 648 | unsigned long flags); |
649 | void clk_unregister_composite(struct clk *clk); | ||
650 | struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name, | ||
651 | const char * const *parent_names, int num_parents, | ||
652 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
653 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, | ||
654 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
655 | unsigned long flags); | ||
656 | void clk_hw_unregister_composite(struct clk_hw *hw); | ||
606 | 657 | ||
607 | /*** | 658 | /*** |
608 | * struct clk_gpio_gate - gpio gated clock | 659 | * struct clk_gpio_gate - gpio gated clock |
@@ -625,6 +676,10 @@ extern const struct clk_ops clk_gpio_gate_ops; | |||
625 | struct clk *clk_register_gpio_gate(struct device *dev, const char *name, | 676 | struct clk *clk_register_gpio_gate(struct device *dev, const char *name, |
626 | const char *parent_name, unsigned gpio, bool active_low, | 677 | const char *parent_name, unsigned gpio, bool active_low, |
627 | unsigned long flags); | 678 | unsigned long flags); |
679 | struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name, | ||
680 | const char *parent_name, unsigned gpio, bool active_low, | ||
681 | unsigned long flags); | ||
682 | void clk_hw_unregister_gpio_gate(struct clk_hw *hw); | ||
628 | 683 | ||
629 | /** | 684 | /** |
630 | * struct clk_gpio_mux - gpio controlled clock multiplexer | 685 | * struct clk_gpio_mux - gpio controlled clock multiplexer |
@@ -640,6 +695,10 @@ extern const struct clk_ops clk_gpio_mux_ops; | |||
640 | struct clk *clk_register_gpio_mux(struct device *dev, const char *name, | 695 | struct clk *clk_register_gpio_mux(struct device *dev, const char *name, |
641 | const char * const *parent_names, u8 num_parents, unsigned gpio, | 696 | const char * const *parent_names, u8 num_parents, unsigned gpio, |
642 | bool active_low, unsigned long flags); | 697 | bool active_low, unsigned long flags); |
698 | struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name, | ||
699 | const char * const *parent_names, u8 num_parents, unsigned gpio, | ||
700 | bool active_low, unsigned long flags); | ||
701 | void clk_hw_unregister_gpio_mux(struct clk_hw *hw); | ||
643 | 702 | ||
644 | /** | 703 | /** |
645 | * clk_register - allocate a new clock, register it and return an opaque cookie | 704 | * clk_register - allocate a new clock, register it and return an opaque cookie |
@@ -655,9 +714,15 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, | |||
655 | struct clk *clk_register(struct device *dev, struct clk_hw *hw); | 714 | struct clk *clk_register(struct device *dev, struct clk_hw *hw); |
656 | struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw); | 715 | struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw); |
657 | 716 | ||
717 | int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw); | ||
718 | int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw); | ||
719 | |||
658 | void clk_unregister(struct clk *clk); | 720 | void clk_unregister(struct clk *clk); |
659 | void devm_clk_unregister(struct device *dev, struct clk *clk); | 721 | void devm_clk_unregister(struct device *dev, struct clk *clk); |
660 | 722 | ||
723 | void clk_hw_unregister(struct clk_hw *hw); | ||
724 | void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); | ||
725 | |||
661 | /* helper functions */ | 726 | /* helper functions */ |
662 | const char *__clk_get_name(const struct clk *clk); | 727 | const char *__clk_get_name(const struct clk *clk); |
663 | const char *clk_hw_get_name(const struct clk_hw *hw); | 728 | const char *clk_hw_get_name(const struct clk_hw *hw); |
@@ -703,6 +768,11 @@ struct clk_onecell_data { | |||
703 | unsigned int clk_num; | 768 | unsigned int clk_num; |
704 | }; | 769 | }; |
705 | 770 | ||
771 | struct clk_hw_onecell_data { | ||
772 | size_t num; | ||
773 | struct clk_hw *hws[]; | ||
774 | }; | ||
775 | |||
706 | extern struct of_device_id __clk_of_table; | 776 | extern struct of_device_id __clk_of_table; |
707 | 777 | ||
708 | #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) | 778 | #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) |
@@ -712,15 +782,24 @@ int of_clk_add_provider(struct device_node *np, | |||
712 | struct clk *(*clk_src_get)(struct of_phandle_args *args, | 782 | struct clk *(*clk_src_get)(struct of_phandle_args *args, |
713 | void *data), | 783 | void *data), |
714 | void *data); | 784 | void *data); |
785 | int of_clk_add_hw_provider(struct device_node *np, | ||
786 | struct clk_hw *(*get)(struct of_phandle_args *clkspec, | ||
787 | void *data), | ||
788 | void *data); | ||
715 | void of_clk_del_provider(struct device_node *np); | 789 | void of_clk_del_provider(struct device_node *np); |
716 | struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, | 790 | struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, |
717 | void *data); | 791 | void *data); |
792 | struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, | ||
793 | void *data); | ||
718 | struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); | 794 | struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); |
795 | struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec, | ||
796 | void *data); | ||
719 | unsigned int of_clk_get_parent_count(struct device_node *np); | 797 | unsigned int of_clk_get_parent_count(struct device_node *np); |
720 | int of_clk_parent_fill(struct device_node *np, const char **parents, | 798 | int of_clk_parent_fill(struct device_node *np, const char **parents, |
721 | unsigned int size); | 799 | unsigned int size); |
722 | const char *of_clk_get_parent_name(struct device_node *np, int index); | 800 | const char *of_clk_get_parent_name(struct device_node *np, int index); |
723 | 801 | int of_clk_detect_critical(struct device_node *np, int index, | |
802 | unsigned long *flags); | ||
724 | void of_clk_init(const struct of_device_id *matches); | 803 | void of_clk_init(const struct of_device_id *matches); |
725 | 804 | ||
726 | #else /* !CONFIG_OF */ | 805 | #else /* !CONFIG_OF */ |
@@ -732,17 +811,34 @@ static inline int of_clk_add_provider(struct device_node *np, | |||
732 | { | 811 | { |
733 | return 0; | 812 | return 0; |
734 | } | 813 | } |
814 | static inline int of_clk_add_hw_provider(struct device_node *np, | ||
815 | struct clk_hw *(*get)(struct of_phandle_args *clkspec, | ||
816 | void *data), | ||
817 | void *data) | ||
818 | { | ||
819 | return 0; | ||
820 | } | ||
735 | static inline void of_clk_del_provider(struct device_node *np) {} | 821 | static inline void of_clk_del_provider(struct device_node *np) {} |
736 | static inline struct clk *of_clk_src_simple_get( | 822 | static inline struct clk *of_clk_src_simple_get( |
737 | struct of_phandle_args *clkspec, void *data) | 823 | struct of_phandle_args *clkspec, void *data) |
738 | { | 824 | { |
739 | return ERR_PTR(-ENOENT); | 825 | return ERR_PTR(-ENOENT); |
740 | } | 826 | } |
827 | static inline struct clk_hw * | ||
828 | of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data) | ||
829 | { | ||
830 | return ERR_PTR(-ENOENT); | ||
831 | } | ||
741 | static inline struct clk *of_clk_src_onecell_get( | 832 | static inline struct clk *of_clk_src_onecell_get( |
742 | struct of_phandle_args *clkspec, void *data) | 833 | struct of_phandle_args *clkspec, void *data) |
743 | { | 834 | { |
744 | return ERR_PTR(-ENOENT); | 835 | return ERR_PTR(-ENOENT); |
745 | } | 836 | } |
837 | static inline struct clk_hw * | ||
838 | of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data) | ||
839 | { | ||
840 | return ERR_PTR(-ENOENT); | ||
841 | } | ||
746 | static inline int of_clk_get_parent_count(struct device_node *np) | 842 | static inline int of_clk_get_parent_count(struct device_node *np) |
747 | { | 843 | { |
748 | return 0; | 844 | return 0; |
@@ -757,6 +853,11 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, | |||
757 | { | 853 | { |
758 | return NULL; | 854 | return NULL; |
759 | } | 855 | } |
856 | static inline int of_clk_detect_critical(struct device_node *np, int index, | ||
857 | unsigned long *flags) | ||
858 | { | ||
859 | return 0; | ||
860 | } | ||
760 | static inline void of_clk_init(const struct of_device_id *matches) {} | 861 | static inline void of_clk_init(const struct of_device_id *matches) {} |
761 | #endif /* CONFIG_OF */ | 862 | #endif /* CONFIG_OF */ |
762 | 863 | ||
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index dc5164a6df29..6110fe09ed18 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h | |||
@@ -37,6 +37,7 @@ | |||
37 | * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() | 37 | * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() |
38 | * @min_divider: minimum valid non-bypass divider value (actual) | 38 | * @min_divider: minimum valid non-bypass divider value (actual) |
39 | * @max_divider: maximum valid non-bypass divider value (actual) | 39 | * @max_divider: maximum valid non-bypass divider value (actual) |
40 | * @max_rate: maximum clock rate for the DPLL | ||
40 | * @modes: possible values of @enable_mask | 41 | * @modes: possible values of @enable_mask |
41 | * @autoidle_reg: register containing the DPLL autoidle mode bitfield | 42 | * @autoidle_reg: register containing the DPLL autoidle mode bitfield |
42 | * @idlest_reg: register containing the DPLL idle status bitfield | 43 | * @idlest_reg: register containing the DPLL idle status bitfield |
@@ -81,6 +82,7 @@ struct dpll_data { | |||
81 | u8 last_rounded_n; | 82 | u8 last_rounded_n; |
82 | u8 min_divider; | 83 | u8 min_divider; |
83 | u16 max_divider; | 84 | u16 max_divider; |
85 | unsigned long max_rate; | ||
84 | u8 modes; | 86 | u8 modes; |
85 | void __iomem *autoidle_reg; | 87 | void __iomem *autoidle_reg; |
86 | void __iomem *idlest_reg; | 88 | void __iomem *idlest_reg; |
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index c2c04f7cbe8a..2eabc862abdb 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/clkdev.h> | 15 | #include <asm/clkdev.h> |
16 | 16 | ||
17 | struct clk; | 17 | struct clk; |
18 | struct clk_hw; | ||
18 | struct device; | 19 | struct device; |
19 | 20 | ||
20 | struct clk_lookup { | 21 | struct clk_lookup { |
@@ -34,18 +35,22 @@ struct clk_lookup { | |||
34 | 35 | ||
35 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, | 36 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, |
36 | const char *dev_fmt, ...) __printf(3, 4); | 37 | const char *dev_fmt, ...) __printf(3, 4); |
38 | struct clk_lookup *clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, | ||
39 | const char *dev_fmt, ...) __printf(3, 4); | ||
37 | 40 | ||
38 | void clkdev_add(struct clk_lookup *cl); | 41 | void clkdev_add(struct clk_lookup *cl); |
39 | void clkdev_drop(struct clk_lookup *cl); | 42 | void clkdev_drop(struct clk_lookup *cl); |
40 | 43 | ||
41 | struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, | 44 | struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id, |
42 | const char *dev_fmt, ...) __printf(3, 4); | 45 | const char *dev_fmt, ...) __printf(3, 4); |
46 | struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id, | ||
47 | const char *dev_fmt, ...) __printf(3, 4); | ||
43 | 48 | ||
44 | void clkdev_add_table(struct clk_lookup *, size_t); | 49 | void clkdev_add_table(struct clk_lookup *, size_t); |
45 | int clk_add_alias(const char *, const char *, const char *, struct device *); | 50 | int clk_add_alias(const char *, const char *, const char *, struct device *); |
46 | 51 | ||
47 | int clk_register_clkdev(struct clk *, const char *, const char *); | 52 | int clk_register_clkdev(struct clk *, const char *, const char *); |
48 | int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t); | 53 | int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *); |
49 | 54 | ||
50 | #ifdef CONFIG_COMMON_CLK | 55 | #ifdef CONFIG_COMMON_CLK |
51 | int __clk_get(struct clk *clk); | 56 | int __clk_get(struct clk *clk); |