History

Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull more clk updates from Stephen Boyd: "Here's some more updates that missed the last pull request because I happened to tag the tree at an earlier point in the history of clk-next. I must have fat fingered it and checked out an older version of clk-next on this second computer I'm using. This time it actually includes more code for Qualcomm SoCs, the AT91 major updates, and some Rockchip SoC clk driver updates as well. I've corrected this flow so this shouldn't happen again" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (83 commits) clk: bcm2835: Do not use prediv with bcm2711's PLLs clk: drop unused function __clk_get_flags clk: hsdk: Fix bad dependency on IOMEM dt-bindings: clock: Fix YAML schemas for LPASS clocks on SC7180 clk: mmp: avoid missing prototype warning clk: sparx5: Add Sparx5 SoC DPLL clock driver dt-bindings: clock: sparx5: Add bindings include file clk: qoriq: add LS1021A core pll mux options clk: clk-atlas6: fix return value check in atlas6_clk_init() clk: tegra: pll: Improve PLLM enable-state detection clk: X1000: Add support for calculat REFCLK of USB PHY. clk: JZ4780: Reformat the code to align it. clk: JZ4780: Add functions for enable and disable USB PHY. clk: Ingenic: Add RTC related clocks for Ingenic SoCs. dt-bindings: clock: Add tabs to align code. dt-bindings: clock: Add RTC related clocks for Ingenic SoCs. clk: davinci: Use fallthrough pseudo-keyword clk: imx: Use fallthrough pseudo-keyword clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk clk: qcom: gcc-sdm660: Add missing modem reset ...

Linus Torvalds committed 6 years ago

Commit 05a5b5d2 parents 4586039 dd9c69782 files · +4778 −871Browse files

Unified · Split

82 files
  1. Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml +9 −0
  2. Documentation/devicetree/bindings/clock/idt,versaclock5.txt +0 −125
  3. Documentation/devicetree/bindings/clock/idt,versaclock5.yaml +154 −0
  4. Documentation/devicetree/bindings/clock/qcom,gpucc.yaml +13 −5
  5. Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml +2 −4
  6. Documentation/devicetree/bindings/clock/qcom,sc7180-gpucc.yaml +0 −74
  7. Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml +108 −0
  8. Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt +7 −1
  9. MAINTAINERS +3 −1
  10. drivers/clk/Kconfig +1 −1
  11. drivers/clk/Makefile +1 −0
  12. drivers/clk/actions/owl-s500.c +88 −1
  13. drivers/clk/at91/Makefile +1 −0
  14. drivers/clk/at91/at91rm9200.c +2 −1
  15. drivers/clk/at91/at91sam9260.c +2 −1
  16. drivers/clk/at91/at91sam9g45.c +3 −2
  17. drivers/clk/at91/at91sam9n12.c +4 −3
  18. drivers/clk/at91/at91sam9rl.c +2 −1
  19. drivers/clk/at91/at91sam9x5.c +4 −3
  20. drivers/clk/at91/clk-generated.c +27 −17
  21. drivers/clk/at91/clk-main.c +3 −3
  22. drivers/clk/at91/clk-master.c +305 −5
  23. drivers/clk/at91/clk-peripheral.c +105 −6
  24. drivers/clk/at91/clk-programmable.c +10 −1
  25. drivers/clk/at91/clk-sam9x60-pll.c +381 −166
  26. drivers/clk/at91/clk-system.c +2 −2
  27. drivers/clk/at91/clk-utmi.c +98 −5
  28. drivers/clk/at91/dt-compat.c +15 −10
  29. drivers/clk/at91/pmc.h +35 −8
  30. drivers/clk/at91/sam9x60.c +49 −17
  31. drivers/clk/at91/sama5d2.c +21 −20
  32. drivers/clk/at91/sama5d3.c +5 −3
  33. drivers/clk/at91/sama5d4.c +4 −3
  34. drivers/clk/at91/sama7g5.c +1059 −0
  35. drivers/clk/at91/sckc.c +3 −2
  36. drivers/clk/bcm/clk-bcm2835.c +21 −4
  37. drivers/clk/bcm/clk-iproc-asiu.c +2 −2
  38. drivers/clk/clk-qoriq.c +9 −1
  39. drivers/clk/clk-sparx5.c +295 −0
  40. drivers/clk/clk-versaclock5.c +38 −44
  41. drivers/clk/clk.c +32 −6
  42. drivers/clk/davinci/pll.c +1 −1
  43. drivers/clk/imx/clk-pllv3.c +2 −2
  44. drivers/clk/ingenic/jz4780-cgu.c +91 −74
  45. drivers/clk/ingenic/x1000-cgu.c +96 −1
  46. drivers/clk/ingenic/x1830-cgu.c +13 −0
  47. drivers/clk/mmp/clk-pxa168.c +1 −0
  48. drivers/clk/mmp/clk-pxa910.c +1 −0
  49. drivers/clk/qcom/Kconfig +25 −0
  50. drivers/clk/qcom/Makefile +3 −0
  51. drivers/clk/qcom/clk-alpha-pll.c +34 −36
  52. drivers/clk/qcom/clk-alpha-pll.h +10 −5
  53. drivers/clk/qcom/gcc-sc7180.c +14 −0
  54. drivers/clk/qcom/gcc-sdm660.c +4 −0
  55. drivers/clk/qcom/gcc-sm8150.c +10 −16
  56. drivers/clk/qcom/gdsc.c +39 −0
  57. drivers/clk/qcom/gdsc.h +2 −0
  58. drivers/clk/qcom/gpucc-sc7180.c +1 −26
  59. drivers/clk/qcom/gpucc-sdm845.c +1 −26
  60. drivers/clk/qcom/gpucc-sm8150.c +320 −0
  61. drivers/clk/qcom/gpucc-sm8250.c +348 −0
  62. drivers/clk/qcom/lpasscorecc-sc7180.c +476 −0
  63. drivers/clk/rockchip/clk-pll.c +41 −29
  64. drivers/clk/rockchip/clk-rk3188.c +1 −0
  65. drivers/clk/rockchip/clk-rk3288.c +36 −3
  66. drivers/clk/rockchip/clk-rk3328.c +4 −4
  67. drivers/clk/sirf/clk-atlas6.c +1 −1
  68. drivers/clk/tegra/clk-pll.c +15 −5
  69. drivers/clk/x86/clk-cgu-pll.c +1 −1
  70. drivers/clk/x86/clk-cgu.c +12 −20
  71. include/dt-bindings/clock/actions,s500-cmu.h +6 −1
  72. include/dt-bindings/clock/jz4780-cgu.h +73 −71
  73. include/dt-bindings/clock/qcom,gcc-sc7180.h +1 −0
  74. include/dt-bindings/clock/qcom,gcc-sdm660.h +1 −0
  75. include/dt-bindings/clock/qcom,gpucc-sm8150.h +33 −0
  76. include/dt-bindings/clock/qcom,gpucc-sm8250.h +34 −0
  77. include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h +29 −0
  78. include/dt-bindings/clock/x1000-cgu.h +2 −0
  79. include/dt-bindings/clock/x1830-cgu.h +2 −0
  80. include/dt-bindings/reset/actions,s500-reset.h +67 −0
  81. include/linux/clk-provider.h +0 −1
  82. include/linux/clk/at91_pmc.h +4 −0
Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml+9−0
@@ -10,6 +10,15 @@ maintainers: · 9 unmodified lines
10 - Eric Anholt <eric@anholt.net>10 - Eric Anholt <eric@anholt.net>
11 - Stefan Wahren <wahrenst@gmx.net>11 - Stefan Wahren <wahrenst@gmx.net>
12 12
13select:
14 properties:
15 compatible:
16 contains:
17 const: raspberrypi,bcm2835-firmware
18
19 required:
20 - compatible
21
13properties:22properties:
14 compatible:23 compatible:
15 items:24 items:
Documentation/devicetree/bindings/clock/idt,versaclock5.txt+0−125
@@ -1,125 +0,0 @@
1Binding for IDT VersaClock 5,6 programmable i2c clock generators.
2
3The IDT VersaClock 5 and VersaClock 6 are programmable i2c clock
4generators providing from 3 to 12 output clocks.
5
6==I2C device node==
7
8Required properties:
9- compatible: shall be one of
10 "idt,5p49v5923"
11 "idt,5p49v5925"
12 "idt,5p49v5933"
13 "idt,5p49v5935"
14 "idt,5p49v6901"
15 "idt,5p49v6965"
16- reg: i2c device address, shall be 0x68 or 0x6a.
17- #clock-cells: from common clock binding; shall be set to 1.
18- clocks: from common clock binding; list of parent clock handles,
19 - 5p49v5923 and
20 5p49v5925 and
21 5p49v6901: (required) either or both of XTAL or CLKIN
22 reference clock.
23 - 5p49v5933 and
24 - 5p49v5935: (optional) property not present (internal
25 Xtal used) or CLKIN reference
26 clock.
27- clock-names: from common clock binding; clock input names, can be
28 - 5p49v5923 and
29 5p49v5925 and
30 5p49v6901: (required) either or both of "xin", "clkin".
31 - 5p49v5933 and
32 - 5p49v5935: (optional) property not present or "clkin".
33
34For all output ports, a corresponding, optional child node named OUT1,
35OUT2, etc. can represent a each output, and the node can be used to
36specify the following:
37
38- itd,mode: can be one of the following:
39 - VC5_LVPECL
40 - VC5_CMOS
41 - VC5_HCSL33
42 - VC5_LVDS
43 - VC5_CMOS2
44 - VC5_CMOSD
45 - VC5_HCSL25
46
47- idt,voltage-microvolts: can be one of the following
48 - 1800000
49 - 2500000
50 - 3300000
51- idt,slew-percent: Percent of normal, can be one of
52 - 80
53 - 85
54 - 90
55 - 100
56
57==Mapping between clock specifier and physical pins==
58
59When referencing the provided clock in the DT using phandle and
60clock specifier, the following mapping applies:
61
625P49V5923:
63 0 -- OUT0_SEL_I2CB
64 1 -- OUT1
65 2 -- OUT2
66
675P49V5933:
68 0 -- OUT0_SEL_I2CB
69 1 -- OUT1
70 2 -- OUT4
71
725P49V5925 and
735P49V5935:
74 0 -- OUT0_SEL_I2CB
75 1 -- OUT1
76 2 -- OUT2
77 3 -- OUT3
78 4 -- OUT4
79
805P49V6901:
81 0 -- OUT0_SEL_I2CB
82 1 -- OUT1
83 2 -- OUT2
84 3 -- OUT3
85 4 -- OUT4
86
87==Example==
88
89/* 25MHz reference crystal */
90ref25: ref25m {
91 compatible = "fixed-clock";
92 #clock-cells = <0>;
93 clock-frequency = <25000000>;
94};
95
96i2c-master-node {
97
98 /* IDT 5P49V5923 i2c clock generator */
99 vc5: clock-generator@6a {
100 compatible = "idt,5p49v5923";
101 reg = <0x6a>;
102 #clock-cells = <1>;
103
104 /* Connect XIN input to 25MHz reference */
105 clocks = <&ref25m>;
106 clock-names = "xin";
107
108 OUT1 {
109 itd,mode = <VC5_CMOS>;
110 idt,voltage-microvolts = <1800000>;
111 idt,slew-percent = <80>;
112 };
113 OUT2 {
114 ...
115 };
116 ...
117 };
118};
119
120/* Consumer referencing the 5P49V5923 pin OUT1 */
121consumer {
122 ...
123 clocks = <&vc5 1>;
124 ...
125}
Documentation/devicetree/bindings/clock/idt,versaclock5.yaml+154−0
@@ -0,0 +1,154 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/clock/idt,versaclock5.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Binding for IDT VersaClock 5 and 6 programmable I2C clock generators
8
9description: |
10 The IDT VersaClock 5 and VersaClock 6 are programmable I2C
11 clock generators providing from 3 to 12 output clocks.
12
13 When referencing the provided clock in the DT using phandle and clock
14 specifier, the following mapping applies:
15
16 - 5P49V5923:
17 0 -- OUT0_SEL_I2CB
18 1 -- OUT1
19 2 -- OUT2
20
21 - 5P49V5933:
22 0 -- OUT0_SEL_I2CB
23 1 -- OUT1
24 2 -- OUT4
25
26 - other parts:
27 0 -- OUT0_SEL_I2CB
28 1 -- OUT1
29 2 -- OUT2
30 3 -- OUT3
31 4 -- OUT4
32
33maintainers:
34 - Luca Ceresoli <luca@lucaceresoli.net>
35
36properties:
37 compatible:
38 enum:
39 - idt,5p49v5923
40 - idt,5p49v5925
41 - idt,5p49v5933
42 - idt,5p49v5935
43 - idt,5p49v6901
44 - idt,5p49v6965
45
46 reg:
47 description: I2C device address
48 enum: [ 0x68, 0x6a ]
49
50 '#clock-cells':
51 const: 1
52
53patternProperties:
54 "^OUT[1-4]$":
55 type: object
56 description:
57 Description of one of the outputs (OUT1..OUT4). See "Clock1 Output
58 Configuration" in the Versaclock 5/6/6E Family Register Description
59 and Programming Guide.
60 properties:
61 idt,mode:
62 description:
63 The output drive mode. Values defined in dt-bindings/clk/versaclock.h
64 $ref: /schemas/types.yaml#/definitions/uint32
65 minimum: 0
66 maximum: 6
67 idt,voltage-microvolt:
68 description: The output drive voltage.
69 enum: [ 1800000, 2500000, 3300000 ]
70 idt,slew-percent:
71 description: The Slew rate control for CMOS single-ended.
72 $ref: /schemas/types.yaml#/definitions/uint32
73 enum: [ 80, 85, 90, 100 ]
74
75required:
76 - compatible
77 - reg
78 - '#clock-cells'
79
80allOf:
81 - if:
82 properties:
83 compatible:
84 enum:
85 - idt,5p49v5933
86 - idt,5p49v5935
87 then:
88 # Devices with builtin crystal + optional external input
89 properties:
90 clock-names:
91 const: clkin
92 clocks:
93 maxItems: 1
94 else:
95 # Devices without builtin crystal
96 properties:
97 clock-names:
98 minItems: 1
99 maxItems: 2
100 items:
101 enum: [ xin, clkin ]
102 clocks:
103 minItems: 1
104 maxItems: 2
105 required:
106 - clock-names
107 - clocks
108
109examples:
110 - |
111 #include <dt-bindings/clk/versaclock.h>
112
113 /* 25MHz reference crystal */
114 ref25: ref25m {
115 compatible = "fixed-clock";
116 #clock-cells = <0>;
117 clock-frequency = <25000000>;
118 };
119
120 i2c@0 {
121 reg = <0x0 0x100>;
122 #address-cells = <1>;
123 #size-cells = <0>;
124
125 /* IDT 5P49V5923 I2C clock generator */
126 vc5: clock-generator@6a {
127 compatible = "idt,5p49v5923";
128 reg = <0x6a>;
129 #clock-cells = <1>;
130
131 /* Connect XIN input to 25MHz reference */
132 clocks = <&ref25m>;
133 clock-names = "xin";
134
135 OUT1 {
136 idt,drive-mode = <VC5_CMOSD>;
137 idt,voltage-microvolts = <1800000>;
138 idt,slew-percent = <80>;
139 };
140
141 OUT4 {
142 idt,drive-mode = <VC5_LVDS>;
143 };
144 };
145 };
146
147 /* Consumer referencing the 5P49V5923 pin OUT1 */
148 consumer {
149 /* ... */
150 clocks = <&vc5 1>;
151 /* ... */
152 };
153
154...
Documentation/devicetree/bindings/clock/qcom,gpucc.yamlrenamed from Documentation/devicetree/bindings/clock/qcom,sdm845-gpucc.yaml+13−5
@@ -1,23 +1,31 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2%YAML 1.22%YAML 1.2
3---3---
4$id: http://devicetree.org/schemas/clock/qcom,sdm845-gpucc.yaml#4$id: http://devicetree.org/schemas/clock/qcom,gpucc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#5$schema: http://devicetree.org/meta-schemas/core.yaml#
6 6
7title: Qualcomm Graphics Clock & Reset Controller Binding for SDM8457title: Qualcomm Graphics Clock & Reset Controller Binding
8 8
9maintainers:9maintainers:
10 - Taniya Das <tdas@codeaurora.org>10 - Taniya Das <tdas@codeaurora.org>
11 11
12description: |12description: |
13 Qualcomm graphics clock control module which supports the clocks, resets and13 Qualcomm graphics clock control module which supports the clocks, resets and
14 power domains on SDM845.14 power domains on SDM845/SC7180/SM8150/SM8250.
15 15
16 See also dt-bindings/clock/qcom,gpucc-sdm845.h.16 See also:
17 dt-bindings/clock/qcom,gpucc-sdm845.h
18 dt-bindings/clock/qcom,gpucc-sc7180.h
19 dt-bindings/clock/qcom,gpucc-sm8150.h
20 dt-bindings/clock/qcom,gpucc-sm8250.h
17 21
18properties:22properties:
19 compatible:23 compatible:
20 const: qcom,sdm845-gpucc24 enum:
25 - qcom,sdm845-gpucc
26 - qcom,sc7180-gpucc
27 - qcom,sm8150-gpucc
28 - qcom,sm8250-gpucc
21 29
22 clocks:30 clocks:
23 items:31 items:
Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml+2−4
@@ -1,7 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2%YAML 1.22%YAML 1.2
3---3---
4$id: http://devicetree.org/schemas/clock/qcom,kryocc.yaml#4$id: http://devicetree.org/schemas/clock/qcom,msm8996-apcc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#5$schema: http://devicetree.org/meta-schemas/core.yaml#
6 6
7title: Qualcomm clock controller for MSM8996 CPUs7title: Qualcomm clock controller for MSM8996 CPUs
@@ -46,11 +46,9 @@ required: · 38 unmodified lines
46additionalProperties: false46additionalProperties: false
47 47
48examples:48examples:
49 # Example for msm8996
50 - |49 - |
51 kryocc: clock-controller@6400000 {50 kryocc: clock-controller@6400000 {
52 compatible = "qcom,msm8996-apcc";51 compatible = "qcom,msm8996-apcc";
53 reg = <0x6400000 0x90000>;52 reg = <0x6400000 0x90000>;
54 #clock-cells = <1>;53 #clock-cells = <1>;
55 };54 };
56...
Documentation/devicetree/bindings/clock/qcom,sc7180-gpucc.yaml+0−74
@@ -1,74 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/clock/qcom,sc7180-gpucc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Qualcomm Graphics Clock & Reset Controller Binding for SC7180
8
9maintainers:
10 - Taniya Das <tdas@codeaurora.org>
11
12description: |
13 Qualcomm graphics clock control module which supports the clocks, resets and
14 power domains on SC7180.
15
16 See also dt-bindings/clock/qcom,gpucc-sc7180.h.
17
18properties:
19 compatible:
20 const: qcom,sc7180-gpucc
21
22 clocks:
23 items:
24 - description: Board XO source
25 - description: GPLL0 main branch source
26 - description: GPLL0 div branch source
27
28 clock-names:
29 items:
30 - const: bi_tcxo
31 - const: gcc_gpu_gpll0_clk_src
32 - const: gcc_gpu_gpll0_div_clk_src
33
34 '#clock-cells':
35 const: 1
36
37 '#reset-cells':
38 const: 1
39
40 '#power-domain-cells':
41 const: 1
42
43 reg:
44 maxItems: 1
45
46required:
47 - compatible
48 - reg
49 - clocks
50 - clock-names
51 - '#clock-cells'
52 - '#reset-cells'
53 - '#power-domain-cells'
54
55additionalProperties: false
56
57examples:
58 - |
59 #include <dt-bindings/clock/qcom,gcc-sc7180.h>
60 #include <dt-bindings/clock/qcom,rpmh.h>
61 clock-controller@5090000 {
62 compatible = "qcom,sc7180-gpucc";
63 reg = <0x05090000 0x9000>;
64 clocks = <&rpmhcc RPMH_CXO_CLK>,
65 <&gcc GCC_GPU_GPLL0_CLK_SRC>,
66 <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>;
67 clock-names = "bi_tcxo",
68 "gcc_gpu_gpll0_clk_src",
69 "gcc_gpu_gpll0_div_clk_src";
70 #clock-cells = <1>;
71 #reset-cells = <1>;
72 #power-domain-cells = <1>;
73 };
74...
Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml+108−0
@@ -0,0 +1,108 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/clock/qcom,sc7180-lpasscorecc.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Qualcomm LPASS Core Clock Controller Binding for SC7180
8
9maintainers:
10 - Taniya Das <tdas@codeaurora.org>
11
12description: |
13 Qualcomm LPASS core clock control module which supports the clocks and
14 power domains on SC7180.
15
16 See also:
17 - dt-bindings/clock/qcom,lpasscorecc-sc7180.h
18
19properties:
20 compatible:
21 enum:
22 - qcom,sc7180-lpasshm
23 - qcom,sc7180-lpasscorecc
24
25 clocks:
26 items:
27 - description: gcc_lpass_sway clock from GCC
28 - description: Board XO source
29
30 clock-names:
31 items:
32 - const: iface
33 - const: bi_tcxo
34
35 power-domains:
36 maxItems: 1
37
38 '#clock-cells':
39 const: 1
40
41 '#power-domain-cells':
42 const: 1
43
44 reg:
45 minItems: 1
46 items:
47 - description: lpass core cc register
48 - description: lpass audio cc register
49
50 reg-names:
51 items:
52 - const: lpass_core_cc
53 - const: lpass_audio_cc
54
55if:
56 properties:
57 compatible:
58 contains:
59 const: qcom,sc7180-lpasshm
60then:
61 properties:
62 reg:
63 maxItems: 1
64
65else:
66 properties:
67 reg:
68 minItems: 2
69
70required:
71 - compatible
72 - reg
73 - clocks
74 - clock-names
75 - '#clock-cells'
76 - '#power-domain-cells'
77
78additionalProperties: false
79
80examples:
81 - |
82 #include <dt-bindings/clock/qcom,rpmh.h>
83 #include <dt-bindings/clock/qcom,gcc-sc7180.h>
84 #include <dt-bindings/clock/qcom,lpasscorecc-sc7180.h>
85 clock-controller@63000000 {
86 compatible = "qcom,sc7180-lpasshm";
87 reg = <0x63000000 0x28>;
88 clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>, <&rpmhcc RPMH_CXO_CLK>;
89 clock-names = "iface", "bi_tcxo";
90 #clock-cells = <1>;
91 #power-domain-cells = <1>;
92 };
93
94 - |
95 #include <dt-bindings/clock/qcom,rpmh.h>
96 #include <dt-bindings/clock/qcom,gcc-sc7180.h>
97 #include <dt-bindings/clock/qcom,lpasscorecc-sc7180.h>
98 clock-controller@62d00000 {
99 compatible = "qcom,sc7180-lpasscorecc";
100 reg = <0x62d00000 0x50000>, <0x62780000 0x30000>;
101 reg-names = "lpass_core_cc", "lpass_audio_cc";
102 clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>, <&rpmhcc RPMH_CXO_CLK>;
103 clock-names = "iface", "bi_tcxo";
104 power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>;
105 #clock-cells = <1>;
106 #power-domain-cells = <1>;
107 };
108...
Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt+7−1
@@ -4,9 +4,15 @@ The RK3288 clock controller generates and supplies clock to various · 3 unmodified lines
4controllers within the SoC and also implements a reset controller for SoC4controllers within the SoC and also implements a reset controller for SoC
5peripherals.5peripherals.
6 6
7A revision of this SoC is available: rk3288w. The clock tree is a bit
8different so another dt-compatible is available. Noticed that it is only
9setting the difference but there is no automatic revision detection. This
10should be performed by bootloaders.
11
7Required Properties:12Required Properties:
8 13
9- compatible: should be "rockchip,rk3288-cru"14- compatible: should be "rockchip,rk3288-cru" or "rockchip,rk3288w-cru" in
15 case of this revision of Rockchip rk3288.
10- reg: physical base address of the controller and length of memory mapped16- reg: physical base address of the controller and length of memory mapped
11 region.17 region.
12- #clock-cells: should be 1.18- #clock-cells: should be 1.
MAINTAINERS+3−1
@@ -1540,6 +1540,7 @@ F: drivers/mmc/host/owl-mmc.c · 1539 unmodified lines
1540F: drivers/pinctrl/actions/*1540F: drivers/pinctrl/actions/*
1541F: drivers/soc/actions/1541F: drivers/soc/actions/
1542F: include/dt-bindings/power/owl-*1542F: include/dt-bindings/power/owl-*
1543F: include/dt-bindings/reset/actions,*
1543F: include/linux/soc/actions/1544F: include/linux/soc/actions/
1544N: owl1545N: owl
1545 1546
@@ -8409,8 +8410,9 @@ W: https://github.com/o2genum/ideapad-slidebar · 6863 unmodified lines
8409F: drivers/input/misc/ideapad_slidebar.c8410F: drivers/input/misc/ideapad_slidebar.c
8410 8411
8411IDT VersaClock 5 CLOCK DRIVER8412IDT VersaClock 5 CLOCK DRIVER
8412M: Marek Vasut <marek.vasut@gmail.com>8413M: Luca Ceresoli <luca@lucaceresoli.net>
8413S: Maintained8414S: Maintained
8415F: Documentation/devicetree/bindings/clock/idt,versaclock5.yaml
8414F: drivers/clk/clk-versaclock5.c8416F: drivers/clk/clk-versaclock5.c
8415 8417
8416IEEE 802.15.4 SUBSYSTEM8418IEEE 802.15.4 SUBSYSTEM
drivers/clk/Kconfig+1−1
@@ -50,7 +50,7 @@ source "drivers/clk/versatile/Kconfig" · 49 unmodified lines
50config CLK_HSDK50config CLK_HSDK
51 bool "PLL Driver for HSDK platform"51 bool "PLL Driver for HSDK platform"
52 depends on OF || COMPILE_TEST52 depends on OF || COMPILE_TEST
53 depends on IOMEM53 depends on HAS_IOMEM
54 help54 help
55 This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs55 This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs
56 control.56 control.
drivers/clk/Makefile+1−0
@@ -28,6 +28,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o · 27 unmodified lines
28obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o28obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
29obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o29obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
30obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o30obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
31obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o
31obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o32obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o
32obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o33obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o
33obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o34obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
drivers/clk/actions/owl-s500.c+88−1
@@ -23,8 +23,10 @@ · 22 unmodified lines
23#include "owl-gate.h"23#include "owl-gate.h"
24#include "owl-mux.h"24#include "owl-mux.h"
25#include "owl-pll.h"25#include "owl-pll.h"
26#include "owl-reset.h"
26 27
27#include <dt-bindings/clock/actions,s500-cmu.h>28#include <dt-bindings/clock/actions,s500-cmu.h>
29#include <dt-bindings/reset/actions,s500-reset.h>
28 30
29#define CMU_COREPLL (0x0000)31#define CMU_COREPLL (0x0000)
30#define CMU_DEVPLL (0x0004)32#define CMU_DEVPLL (0x0004)
@@ -175,6 +177,8 @@ static OWL_MUX(dev_clk, "dev_clk", dev_clk_mux_p, CMU_DEVPLL, 12, 1, CLK_SET_RAT · 144 unmodified lines
175static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT);177static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT);
176 178
177/* gate clocks */179/* gate clocks */
180static OWL_GATE(gpio_clk, "gpio_clk", "apb_clk", CMU_DEVCLKEN0, 18, 0, 0);
181static OWL_GATE(dmac_clk, "dmac_clk", "h_clk", CMU_DEVCLKEN0, 1, 0, 0);
178static OWL_GATE(spi0_clk, "spi0_clk", "ahb_clk", CMU_DEVCLKEN1, 10, 0, CLK_IGNORE_UNUSED);182static OWL_GATE(spi0_clk, "spi0_clk", "ahb_clk", CMU_DEVCLKEN1, 10, 0, CLK_IGNORE_UNUSED);
179static OWL_GATE(spi1_clk, "spi1_clk", "ahb_clk", CMU_DEVCLKEN1, 11, 0, CLK_IGNORE_UNUSED);183static OWL_GATE(spi1_clk, "spi1_clk", "ahb_clk", CMU_DEVCLKEN1, 11, 0, CLK_IGNORE_UNUSED);
180static OWL_GATE(spi2_clk, "spi2_clk", "ahb_clk", CMU_DEVCLKEN1, 12, 0, CLK_IGNORE_UNUSED);184static OWL_GATE(spi2_clk, "spi2_clk", "ahb_clk", CMU_DEVCLKEN1, 12, 0, CLK_IGNORE_UNUSED);
@@ -183,7 +187,8 @@ static OWL_GATE(timer_clk, "timer_clk", "hosc", CMU_DEVCLKEN1, 27, 0, 0); · 2 unmodified lines
183static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0);187static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0);
184 188
185/* divider clocks */189/* divider clocks */
186static OWL_DIVIDER(h_clk, "h_clk", "ahbprevdiv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0);190static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0);
191static OWL_DIVIDER(apb_clk, "apb_clk", "ahb_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0);
187static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0);192static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0);
188 193
189/* factor clocks */194/* factor clocks */
@@ -428,6 +433,9 @@ static struct owl_clk_common *s500_clks[] = { · 238 unmodified lines
428 &spdif_clk.common,433 &spdif_clk.common,
429 &nand_clk.common,434 &nand_clk.common,
430 &ecc_clk.common,435 &ecc_clk.common,
436 &apb_clk.common,
437 &dmac_clk.common,
438 &gpio_clk.common,
431};439};
432 440
433static struct clk_hw_onecell_data s500_hw_clks = {441static struct clk_hw_onecell_data s500_hw_clks = {
@@ -484,24 +492,103 @@ static struct clk_hw_onecell_data s500_hw_clks = { · 50 unmodified lines
484 [CLK_SPDIF] = &spdif_clk.common.hw,492 [CLK_SPDIF] = &spdif_clk.common.hw,
485 [CLK_NAND] = &nand_clk.common.hw,493 [CLK_NAND] = &nand_clk.common.hw,
486 [CLK_ECC] = &ecc_clk.common.hw,494 [CLK_ECC] = &ecc_clk.common.hw,
495 [CLK_APB] = &apb_clk.common.hw,
496 [CLK_DMAC] = &dmac_clk.common.hw,
497 [CLK_GPIO] = &gpio_clk.common.hw,
487 },498 },
488 .num = CLK_NR_CLKS,499 .num = CLK_NR_CLKS,
489};500};
490 501
502static const struct owl_reset_map s500_resets[] = {
503 [RESET_DMAC] = { CMU_DEVRST0, BIT(0) },
504 [RESET_NORIF] = { CMU_DEVRST0, BIT(1) },
505 [RESET_DDR] = { CMU_DEVRST0, BIT(2) },
506 [RESET_NANDC] = { CMU_DEVRST0, BIT(3) },
507 [RESET_SD0] = { CMU_DEVRST0, BIT(4) },
508 [RESET_SD1] = { CMU_DEVRST0, BIT(5) },
509 [RESET_PCM1] = { CMU_DEVRST0, BIT(6) },
510 [RESET_DE] = { CMU_DEVRST0, BIT(7) },
511 [RESET_LCD] = { CMU_DEVRST0, BIT(8) },
512 [RESET_SD2] = { CMU_DEVRST0, BIT(9) },
513 [RESET_DSI] = { CMU_DEVRST0, BIT(10) },
514 [RESET_CSI] = { CMU_DEVRST0, BIT(11) },
515 [RESET_BISP] = { CMU_DEVRST0, BIT(12) },
516 [RESET_KEY] = { CMU_DEVRST0, BIT(14) },
517 [RESET_GPIO] = { CMU_DEVRST0, BIT(15) },
518 [RESET_AUDIO] = { CMU_DEVRST0, BIT(17) },
519 [RESET_PCM0] = { CMU_DEVRST0, BIT(18) },
520 [RESET_VDE] = { CMU_DEVRST0, BIT(19) },
521 [RESET_VCE] = { CMU_DEVRST0, BIT(20) },
522 [RESET_GPU3D] = { CMU_DEVRST0, BIT(22) },
523 [RESET_NIC301] = { CMU_DEVRST0, BIT(23) },
524 [RESET_LENS] = { CMU_DEVRST0, BIT(26) },
525 [RESET_PERIPHRESET] = { CMU_DEVRST0, BIT(27) },
526 [RESET_USB2_0] = { CMU_DEVRST1, BIT(0) },
527 [RESET_TVOUT] = { CMU_DEVRST1, BIT(1) },
528 [RESET_HDMI] = { CMU_DEVRST1, BIT(2) },
529 [RESET_HDCP2TX] = { CMU_DEVRST1, BIT(3) },
530 [RESET_UART6] = { CMU_DEVRST1, BIT(4) },
531 [RESET_UART0] = { CMU_DEVRST1, BIT(5) },
532 [RESET_UART1] = { CMU_DEVRST1, BIT(6) },
533 [RESET_UART2] = { CMU_DEVRST1, BIT(7) },
534 [RESET_SPI0] = { CMU_DEVRST1, BIT(8) },
535 [RESET_SPI1] = { CMU_DEVRST1, BIT(9) },
536 [RESET_SPI2] = { CMU_DEVRST1, BIT(10) },
537 [RESET_SPI3] = { CMU_DEVRST1, BIT(11) },
538 [RESET_I2C0] = { CMU_DEVRST1, BIT(12) },
539 [RESET_I2C1] = { CMU_DEVRST1, BIT(13) },
540 [RESET_USB3] = { CMU_DEVRST1, BIT(14) },
541 [RESET_UART3] = { CMU_DEVRST1, BIT(15) },
542 [RESET_UART4] = { CMU_DEVRST1, BIT(16) },
543 [RESET_UART5] = { CMU_DEVRST1, BIT(17) },
544 [RESET_I2C2] = { CMU_DEVRST1, BIT(18) },
545 [RESET_I2C3] = { CMU_DEVRST1, BIT(19) },
546 [RESET_ETHERNET] = { CMU_DEVRST1, BIT(20) },
547 [RESET_CHIPID] = { CMU_DEVRST1, BIT(21) },
548 [RESET_USB2_1] = { CMU_DEVRST1, BIT(22) },
549 [RESET_WD0RESET] = { CMU_DEVRST1, BIT(24) },
550 [RESET_WD1RESET] = { CMU_DEVRST1, BIT(25) },
551 [RESET_WD2RESET] = { CMU_DEVRST1, BIT(26) },
552 [RESET_WD3RESET] = { CMU_DEVRST1, BIT(27) },
553 [RESET_DBG0RESET] = { CMU_DEVRST1, BIT(28) },
554 [RESET_DBG1RESET] = { CMU_DEVRST1, BIT(29) },
555 [RESET_DBG2RESET] = { CMU_DEVRST1, BIT(30) },
556 [RESET_DBG3RESET] = { CMU_DEVRST1, BIT(31) },
557};
558
491static struct owl_clk_desc s500_clk_desc = {559static struct owl_clk_desc s500_clk_desc = {
492 .clks = s500_clks,560 .clks = s500_clks,
493 .num_clks = ARRAY_SIZE(s500_clks),561 .num_clks = ARRAY_SIZE(s500_clks),
494 562
495 .hw_clks = &s500_hw_clks,563 .hw_clks = &s500_hw_clks,
564
565 .resets = s500_resets,
566 .num_resets = ARRAY_SIZE(s500_resets),
496};567};
497 568
498static int s500_clk_probe(struct platform_device *pdev)569static int s500_clk_probe(struct platform_device *pdev)
499{570{
500 struct owl_clk_desc *desc;571 struct owl_clk_desc *desc;
572 struct owl_reset *reset;
573 int ret;
501 574
502 desc = &s500_clk_desc;575 desc = &s500_clk_desc;
503 owl_clk_regmap_init(pdev, desc);576 owl_clk_regmap_init(pdev, desc);
504 577
578 reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
579 if (!reset)
580 return -ENOMEM;
581
582 reset->rcdev.of_node = pdev->dev.of_node;
583 reset->rcdev.ops = &owl_reset_ops;
584 reset->rcdev.nr_resets = desc->num_resets;
585 reset->reset_map = desc->resets;
586 reset->regmap = desc->regmap;
587
588 ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
589 if (ret)
590 dev_err(&pdev->dev, "Failed to register reset controller\n");
591
505 return owl_clk_probe(&pdev->dev, desc->hw_clks);592 return owl_clk_probe(&pdev->dev, desc->hw_clks);
506}593}
507 594
drivers/clk/at91/Makefile+1−0
@@ -23,3 +23,4 @@ obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o · 22 unmodified lines
23obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o23obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o
24obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o24obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
25obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o25obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
26obj-$(CONFIG_SOC_SAMA7G5) += sama7g5.o
drivers/clk/at91/at91rm9200.c+2−1
@@ -160,7 +160,8 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) · 159 unmodified lines
160 160
161 hw = at91_clk_register_programmable(regmap, name,161 hw = at91_clk_register_programmable(regmap, name,
162 parent_names, 4, i,162 parent_names, 4, i,
163 &at91rm9200_programmable_layout);163 &at91rm9200_programmable_layout,
164 NULL);
164 if (IS_ERR(hw))165 if (IS_ERR(hw))
165 goto err_free;166 goto err_free;
166 167
drivers/clk/at91/at91sam9260.c+2−1
@@ -436,7 +436,8 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, · 435 unmodified lines
436 436
437 hw = at91_clk_register_programmable(regmap, name,437 hw = at91_clk_register_programmable(regmap, name,
438 parent_names, 4, i,438 parent_names, 4, i,
439 &at91rm9200_programmable_layout);439 &at91rm9200_programmable_layout,
440 NULL);
440 if (IS_ERR(hw))441 if (IS_ERR(hw))
441 goto err_free;442 goto err_free;
442 443
drivers/clk/at91/at91sam9g45.c+3−2
@@ -111,7 +111,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) · 110 unmodified lines
111 return;111 return;
112 mainxtal_name = of_clk_get_parent_name(np, i);112 mainxtal_name = of_clk_get_parent_name(np, i);
113 113
114 regmap = syscon_node_to_regmap(np);114 regmap = device_node_to_regmap(np);
115 if (IS_ERR(regmap))115 if (IS_ERR(regmap))
116 return;116 return;
117 117
@@ -181,7 +181,8 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) · 63 unmodified lines
181 181
182 hw = at91_clk_register_programmable(regmap, name,182 hw = at91_clk_register_programmable(regmap, name,
183 parent_names, 5, i,183 parent_names, 5, i,
184 &at91sam9g45_programmable_layout);184 &at91sam9g45_programmable_layout,
185 NULL);
185 if (IS_ERR(hw))186 if (IS_ERR(hw))
186 goto err_free;187 goto err_free;
187 188
drivers/clk/at91/at91sam9n12.c+4−3
@@ -124,7 +124,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) · 123 unmodified lines
124 return;124 return;
125 mainxtal_name = of_clk_get_parent_name(np, i);125 mainxtal_name = of_clk_get_parent_name(np, i);
126 126
127 regmap = syscon_node_to_regmap(np);127 regmap = device_node_to_regmap(np);
128 if (IS_ERR(regmap))128 if (IS_ERR(regmap))
129 return;129 return;
130 130
@@ -199,7 +199,8 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) · 68 unmodified lines
199 199
200 hw = at91_clk_register_programmable(regmap, name,200 hw = at91_clk_register_programmable(regmap, name,
201 parent_names, 5, i,201 parent_names, 5, i,
202 &at91sam9x5_programmable_layout);202 &at91sam9x5_programmable_layout,
203 NULL);
203 if (IS_ERR(hw))204 if (IS_ERR(hw))
204 goto err_free;205 goto err_free;
205 206
@@ -222,7 +223,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) · 16 unmodified lines
222 at91sam9n12_periphck[i].n,223 at91sam9n12_periphck[i].n,
223 "masterck",224 "masterck",
224 at91sam9n12_periphck[i].id,225 at91sam9n12_periphck[i].id,
225 &range);226 &range, INT_MIN);
226 if (IS_ERR(hw))227 if (IS_ERR(hw))
227 goto err_free;228 goto err_free;
228 229
drivers/clk/at91/at91sam9rl.c+2−1
@@ -137,7 +137,8 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) · 136 unmodified lines
137 137
138 hw = at91_clk_register_programmable(regmap, name,138 hw = at91_clk_register_programmable(regmap, name,
139 parent_names, 5, i,139 parent_names, 5, i,
140 &at91rm9200_programmable_layout);140 &at91rm9200_programmable_layout,
141 NULL);
141 if (IS_ERR(hw))142 if (IS_ERR(hw))
142 goto err_free;143 goto err_free;
143 144
drivers/clk/at91/at91sam9x5.c+4−3
@@ -226,7 +226,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, · 225 unmodified lines
226 226
227 hw = at91_clk_register_programmable(regmap, name,227 hw = at91_clk_register_programmable(regmap, name,
228 parent_names, 5, i,228 parent_names, 5, i,
229 &at91sam9x5_programmable_layout);229 &at91sam9x5_programmable_layout,
230 NULL);
230 if (IS_ERR(hw))231 if (IS_ERR(hw))
231 goto err_free;232 goto err_free;
232 233
@@ -257,7 +258,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, · 24 unmodified lines
257 at91sam9x5_periphck[i].n,258 at91sam9x5_periphck[i].n,
258 "masterck",259 "masterck",
259 at91sam9x5_periphck[i].id,260 at91sam9x5_periphck[i].id,
260 &range);261 &range, INT_MIN);
261 if (IS_ERR(hw))262 if (IS_ERR(hw))
262 goto err_free;263 goto err_free;
263 264
@@ -270,7 +271,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, · 6 unmodified lines
270 extra_pcks[i].n,271 extra_pcks[i].n,
271 "masterck",272 "masterck",
272 extra_pcks[i].id,273 extra_pcks[i].id,
273 &range);274 &range, INT_MIN);
274 if (IS_ERR(hw))275 if (IS_ERR(hw))
275 goto err_free;276 goto err_free;
276 277
drivers/clk/at91/clk-generated.c+27−17
@@ -18,18 +18,17 @@ · 17 unmodified lines
18 18
19#define GENERATED_MAX_DIV 25519#define GENERATED_MAX_DIV 255
20 20
21#define GCK_INDEX_DT_AUDIO_PLL 5
22
23struct clk_generated {21struct clk_generated {
24 struct clk_hw hw;22 struct clk_hw hw;
25 struct regmap *regmap;23 struct regmap *regmap;
26 struct clk_range range;24 struct clk_range range;
27 spinlock_t *lock;25 spinlock_t *lock;
26 u32 *mux_table;
28 u32 id;27 u32 id;
29 u32 gckdiv;28 u32 gckdiv;
30 const struct clk_pcr_layout *layout;29 const struct clk_pcr_layout *layout;
31 u8 parent_id;30 u8 parent_id;
32 bool audio_pll_allowed;31 int chg_pid;
33};32};
34 33
35#define to_clk_generated(hw) \34#define to_clk_generated(hw) \
@@ -83,7 +82,7 @@ static int clk_generated_is_enabled(struct clk_hw *hw) · 47 unmodified lines
83 regmap_read(gck->regmap, gck->layout->offset, &status);82 regmap_read(gck->regmap, gck->layout->offset, &status);
84 spin_unlock_irqrestore(gck->lock, flags);83 spin_unlock_irqrestore(gck->lock, flags);
85 84
86 return status & AT91_PMC_PCR_GCKEN ? 1 : 0;85 return !!(status & AT91_PMC_PCR_GCKEN);
87}86}
88 87
89static unsigned long88static unsigned long
@@ -109,7 +108,7 @@ static void clk_generated_best_diff(struct clk_rate_request *req, · 19 unmodified lines
109 tmp_rate = parent_rate / div;108 tmp_rate = parent_rate / div;
110 tmp_diff = abs(req->rate - tmp_rate);109 tmp_diff = abs(req->rate - tmp_rate);
111 110
112 if (*best_diff < 0 || *best_diff > tmp_diff) {111 if (*best_diff < 0 || *best_diff >= tmp_diff) {
113 *best_rate = tmp_rate;112 *best_rate = tmp_rate;
114 *best_diff = tmp_diff;113 *best_diff = tmp_diff;
115 req->best_parent_rate = parent_rate;114 req->best_parent_rate = parent_rate;
@@ -129,7 +128,10 @@ static int clk_generated_determine_rate(struct clk_hw *hw, · 13 unmodified lines
129 int i;128 int i;
130 u32 div;129 u32 div;
131 130
132 for (i = 0; i < clk_hw_get_num_parents(hw) - 1; i++) {131 for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
132 if (gck->chg_pid == i)
133 continue;
134
133 parent = clk_hw_get_parent_by_index(hw, i);135 parent = clk_hw_get_parent_by_index(hw, i);
134 if (!parent)136 if (!parent)
135 continue;137 continue;
@@ -161,16 +163,17 @@ static int clk_generated_determine_rate(struct clk_hw *hw, · 25 unmodified lines
161 * that the only clks able to modify gck rate are those of audio IPs.163 * that the only clks able to modify gck rate are those of audio IPs.
162 */164 */
163 165
164 if (!gck->audio_pll_allowed)166 if (gck->chg_pid < 0)
165 goto end;167 goto end;
166 168
167 parent = clk_hw_get_parent_by_index(hw, GCK_INDEX_DT_AUDIO_PLL);169 parent = clk_hw_get_parent_by_index(hw, gck->chg_pid);
168 if (!parent)170 if (!parent)
169 goto end;171 goto end;
170 172
171 for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {173 for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
172 req_parent.rate = req->rate * div;174 req_parent.rate = req->rate * div;
173 __clk_determine_rate(parent, &req_parent);175 if (__clk_determine_rate(parent, &req_parent))
176 continue;
174 clk_generated_best_diff(req, parent, req_parent.rate, div,177 clk_generated_best_diff(req, parent, req_parent.rate, div,
175 &best_diff, &best_rate);178 &best_diff, &best_rate);
176 179
@@ -184,8 +187,8 @@ end: · 7 unmodified lines
184 __clk_get_name((req->best_parent_hw)->clk),187 __clk_get_name((req->best_parent_hw)->clk),
185 req->best_parent_rate);188 req->best_parent_rate);
186 189
187 if (best_rate < 0)190 if (best_rate < 0 || (gck->range.max && best_rate > gck->range.max))
188 return best_rate;191 return -EINVAL;
189 192
190 req->rate = best_rate;193 req->rate = best_rate;
191 return 0;194 return 0;
@@ -199,7 +202,11 @@ static int clk_generated_set_parent(struct clk_hw *hw, u8 index) · 7 unmodified lines
199 if (index >= clk_hw_get_num_parents(hw))202 if (index >= clk_hw_get_num_parents(hw))
200 return -EINVAL;203 return -EINVAL;
201 204
202 gck->parent_id = index;205 if (gck->mux_table)
206 gck->parent_id = clk_mux_index_to_val(gck->mux_table, 0, index);
207 else
208 gck->parent_id = index;
209
203 return 0;210 return 0;
204}211}
205 212
@@ -271,8 +278,9 @@ struct clk_hw * __init · 65 unmodified lines
271at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,278at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
272 const struct clk_pcr_layout *layout,279 const struct clk_pcr_layout *layout,
273 const char *name, const char **parent_names,280 const char *name, const char **parent_names,
274 u8 num_parents, u8 id, bool pll_audio,281 u32 *mux_table, u8 num_parents, u8 id,
275 const struct clk_range *range)282 const struct clk_range *range,
283 int chg_pid)
276{284{
277 struct clk_generated *gck;285 struct clk_generated *gck;
278 struct clk_init_data init;286 struct clk_init_data init;
@@ -287,16 +295,18 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, · 8 unmodified lines
287 init.ops = &generated_ops;295 init.ops = &generated_ops;
288 init.parent_names = parent_names;296 init.parent_names = parent_names;
289 init.num_parents = num_parents;297 init.num_parents = num_parents;
290 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |298 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
291 CLK_SET_RATE_PARENT;299 if (chg_pid >= 0)
300 init.flags |= CLK_SET_RATE_PARENT;
292 301
293 gck->id = id;302 gck->id = id;
294 gck->hw.init = &init;303 gck->hw.init = &init;
295 gck->regmap = regmap;304 gck->regmap = regmap;
296 gck->lock = lock;305 gck->lock = lock;
297 gck->range = *range;306 gck->range = *range;
298 gck->audio_pll_allowed = pll_audio;307 gck->chg_pid = chg_pid;
299 gck->layout = layout;308 gck->layout = layout;
309 gck->mux_table = mux_table;
300 310
301 clk_generated_startup(gck);311 clk_generated_startup(gck);
302 hw = &gck->hw;312 hw = &gck->hw;
drivers/clk/at91/clk-main.c+3−3
@@ -175,7 +175,7 @@ static bool clk_main_rc_osc_ready(struct regmap *regmap) · 174 unmodified lines
175 175
176 regmap_read(regmap, AT91_PMC_SR, &status);176 regmap_read(regmap, AT91_PMC_SR, &status);
177 177
178 return status & AT91_PMC_MOSCRCS;178 return !!(status & AT91_PMC_MOSCRCS);
179}179}
180 180
181static int clk_main_rc_osc_prepare(struct clk_hw *hw)181static int clk_main_rc_osc_prepare(struct clk_hw *hw)
@@ -336,7 +336,7 @@ static int clk_rm9200_main_is_prepared(struct clk_hw *hw) · 154 unmodified lines
336 336
337 regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);337 regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
338 338
339 return status & AT91_PMC_MAINRDY ? 1 : 0;339 return !!(status & AT91_PMC_MAINRDY);
340}340}
341 341
342static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,342static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
@@ -398,7 +398,7 @@ static inline bool clk_sam9x5_main_ready(struct regmap *regmap) · 55 unmodified lines
398 398
399 regmap_read(regmap, AT91_PMC_SR, &status);399 regmap_read(regmap, AT91_PMC_SR, &status);
400 400
401 return status & AT91_PMC_MOSCSELS ? 1 : 0;401 return !!(status & AT91_PMC_MOSCSELS);
402}402}
403 403
404static int clk_sam9x5_main_prepare(struct clk_hw *hw)404static int clk_sam9x5_main_prepare(struct clk_hw *hw)
drivers/clk/at91/clk-master.c+305−5
@@ -17,30 +17,49 @@ · 16 unmodified lines
17#define MASTER_DIV_SHIFT 817#define MASTER_DIV_SHIFT 8
18#define MASTER_DIV_MASK 0x318#define MASTER_DIV_MASK 0x3
19 19
20#define PMC_MCR 0x30
21#define PMC_MCR_ID_MSK GENMASK(3, 0)
22#define PMC_MCR_CMD BIT(7)
23#define PMC_MCR_DIV GENMASK(10, 8)
24#define PMC_MCR_CSS GENMASK(20, 16)
25#define PMC_MCR_CSS_SHIFT (16)
26#define PMC_MCR_EN BIT(28)
27
28#define PMC_MCR_ID(x) ((x) & PMC_MCR_ID_MSK)
29
30#define MASTER_MAX_ID 4
31
20#define to_clk_master(hw) container_of(hw, struct clk_master, hw)32#define to_clk_master(hw) container_of(hw, struct clk_master, hw)
21 33
22struct clk_master {34struct clk_master {
23 struct clk_hw hw;35 struct clk_hw hw;
24 struct regmap *regmap;36 struct regmap *regmap;
37 spinlock_t *lock;
25 const struct clk_master_layout *layout;38 const struct clk_master_layout *layout;
26 const struct clk_master_characteristics *characteristics;39 const struct clk_master_characteristics *characteristics;
40 u32 *mux_table;
27 u32 mckr;41 u32 mckr;
42 int chg_pid;
43 u8 id;
44 u8 parent;
45 u8 div;
28};46};
29 47
30static inline bool clk_master_ready(struct regmap *regmap)48static inline bool clk_master_ready(struct clk_master *master)
31{49{
50 unsigned int bit = master->id ? AT91_PMC_MCKXRDY : AT91_PMC_MCKRDY;
32 unsigned int status;51 unsigned int status;
33 52
34 regmap_read(regmap, AT91_PMC_SR, &status);53 regmap_read(master->regmap, AT91_PMC_SR, &status);
35 54
36 return status & AT91_PMC_MCKRDY ? 1 : 0;55 return !!(status & bit);
37}56}
38 57
39static int clk_master_prepare(struct clk_hw *hw)58static int clk_master_prepare(struct clk_hw *hw)
40{59{
41 struct clk_master *master = to_clk_master(hw);60 struct clk_master *master = to_clk_master(hw);
42 61
43 while (!clk_master_ready(master->regmap))62 while (!clk_master_ready(master))
44 cpu_relax();63 cpu_relax();
45 64
46 return 0;65 return 0;
@@ -50,7 +69,7 @@ static int clk_master_is_prepared(struct clk_hw *hw) · 3 unmodified lines
50{69{
51 struct clk_master *master = to_clk_master(hw);70 struct clk_master *master = to_clk_master(hw);
52 71
53 return clk_master_ready(master->regmap);72 return clk_master_ready(master);
54}73}
55 74
56static unsigned long clk_master_recalc_rate(struct clk_hw *hw,75static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
@@ -143,6 +162,287 @@ at91_clk_register_master(struct regmap *regmap, · 86 unmodified lines
143 return hw;162 return hw;
144}163}
145 164
165static unsigned long
166clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
167 unsigned long parent_rate)
168{
169 struct clk_master *master = to_clk_master(hw);
170
171 return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
172}
173
174static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
175 struct clk_hw *parent,
176 unsigned long parent_rate,
177 long *best_rate,
178 long *best_diff,
179 u32 div)
180{
181 unsigned long tmp_rate, tmp_diff;
182
183 if (div == MASTER_PRES_MAX)
184 tmp_rate = parent_rate / 3;
185 else
186 tmp_rate = parent_rate >> div;
187
188 tmp_diff = abs(req->rate - tmp_rate);
189
190 if (*best_diff < 0 || *best_diff >= tmp_diff) {
191 *best_rate = tmp_rate;
192 *best_diff = tmp_diff;
193 req->best_parent_rate = parent_rate;
194 req->best_parent_hw = parent;
195 }
196}
197
198static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
199 struct clk_rate_request *req)
200{
201 struct clk_master *master = to_clk_master(hw);
202 struct clk_rate_request req_parent = *req;
203 struct clk_hw *parent;
204 long best_rate = LONG_MIN, best_diff = LONG_MIN;
205 unsigned long parent_rate;
206 unsigned int div, i;
207
208 /* First: check the dividers of MCR. */
209 for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
210 parent = clk_hw_get_parent_by_index(hw, i);
211 if (!parent)
212 continue;
213
214 parent_rate = clk_hw_get_rate(parent);
215 if (!parent_rate)
216 continue;
217
218 for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
219 clk_sama7g5_master_best_diff(req, parent, parent_rate,
220 &best_rate, &best_diff,
221 div);
222 if (!best_diff)
223 break;
224 }
225
226 if (!best_diff)
227 break;
228 }
229
230 /* Second: try to request rate form changeable parent. */
231 if (master->chg_pid < 0)
232 goto end;
233
234 parent = clk_hw_get_parent_by_index(hw, master->chg_pid);
235 if (!parent)
236 goto end;
237
238 for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
239 if (div == MASTER_PRES_MAX)
240 req_parent.rate = req->rate * 3;
241 else
242 req_parent.rate = req->rate << div;
243
244 if (__clk_determine_rate(parent, &req_parent))
245 continue;
246
247 clk_sama7g5_master_best_diff(req, parent, req_parent.rate,
248 &best_rate, &best_diff, div);
249
250 if (!best_diff)
251 break;
252 }
253
254end:
255 pr_debug("MCK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
256 __func__, best_rate,
257 __clk_get_name((req->best_parent_hw)->clk),
258 req->best_parent_rate);
259
260 if (best_rate < 0)
261 return -EINVAL;
262
263 req->rate = best_rate;
264
265 return 0;
266}
267
268static u8 clk_sama7g5_master_get_parent(struct clk_hw *hw)
269{
270 struct clk_master *master = to_clk_master(hw);
271 unsigned long flags;
272 u8 index;
273
274 spin_lock_irqsave(master->lock, flags);
275 index = clk_mux_val_to_index(&master->hw, master->mux_table, 0,
276 master->parent);
277 spin_unlock_irqrestore(master->lock, flags);
278
279 return index;
280}
281
282static int clk_sama7g5_master_set_parent(struct clk_hw *hw, u8 index)
283{
284 struct clk_master *master = to_clk_master(hw);
285 unsigned long flags;
286
287 if (index >= clk_hw_get_num_parents(hw))
288 return -EINVAL;
289
290 spin_lock_irqsave(master->lock, flags);
291 master->parent = clk_mux_index_to_val(master->mux_table, 0, index);
292 spin_unlock_irqrestore(master->lock, flags);
293
294 return 0;
295}
296
297static int clk_sama7g5_master_enable(struct clk_hw *hw)
298{
299 struct clk_master *master = to_clk_master(hw);
300 unsigned long flags;
301 unsigned int val, cparent;
302
303 spin_lock_irqsave(master->lock, flags);
304
305 regmap_write(master->regmap, PMC_MCR, PMC_MCR_ID(master->id));
306 regmap_read(master->regmap, PMC_MCR, &val);
307 regmap_update_bits(master->regmap, PMC_MCR,
308 PMC_MCR_EN | PMC_MCR_CSS | PMC_MCR_DIV |
309 PMC_MCR_CMD | PMC_MCR_ID_MSK,
310 PMC_MCR_EN | (master->parent << PMC_MCR_CSS_SHIFT) |
311 (master->div << MASTER_DIV_SHIFT) |
312 PMC_MCR_CMD | PMC_MCR_ID(master->id));
313
314 cparent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
315
316 /* Wait here only if parent is being changed. */
317 while ((cparent != master->parent) && !clk_master_ready(master))
318 cpu_relax();
319
320 spin_unlock_irqrestore(master->lock, flags);
321
322 return 0;
323}
324
325static void clk_sama7g5_master_disable(struct clk_hw *hw)
326{
327 struct clk_master *master = to_clk_master(hw);
328 unsigned long flags;
329
330 spin_lock_irqsave(master->lock, flags);
331
332 regmap_write(master->regmap, PMC_MCR, master->id);
333 regmap_update_bits(master->regmap, PMC_MCR,
334 PMC_MCR_EN | PMC_MCR_CMD | PMC_MCR_ID_MSK,
335 PMC_MCR_CMD | PMC_MCR_ID(master->id));
336
337 spin_unlock_irqrestore(master->lock, flags);
338}
339
340static int clk_sama7g5_master_is_enabled(struct clk_hw *hw)
341{
342 struct clk_master *master = to_clk_master(hw);
343 unsigned long flags;
344 unsigned int val;
345
346 spin_lock_irqsave(master->lock, flags);
347
348 regmap_write(master->regmap, PMC_MCR, master->id);
349 regmap_read(master->regmap, PMC_MCR, &val);
350
351 spin_unlock_irqrestore(master->lock, flags);
352
353 return !!(val & PMC_MCR_EN);
354}
355
356static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
357 unsigned long parent_rate)
358{
359 struct clk_master *master = to_clk_master(hw);
360 unsigned long div, flags;
361
362 div = DIV_ROUND_CLOSEST(parent_rate, rate);
363 if ((div > (1 << (MASTER_PRES_MAX - 1))) || (div & (div - 1)))
364 return -EINVAL;
365
366 if (div == 3)
367 div = MASTER_PRES_MAX;
368 else
369 div = ffs(div) - 1;
370
371 spin_lock_irqsave(master->lock, flags);
372 master->div = div;
373 spin_unlock_irqrestore(master->lock, flags);
374
375 return 0;
376}
377
378static const struct clk_ops sama7g5_master_ops = {
379 .enable = clk_sama7g5_master_enable,
380 .disable = clk_sama7g5_master_disable,
381 .is_enabled = clk_sama7g5_master_is_enabled,
382 .recalc_rate = clk_sama7g5_master_recalc_rate,
383 .determine_rate = clk_sama7g5_master_determine_rate,
384 .set_rate = clk_sama7g5_master_set_rate,
385 .get_parent = clk_sama7g5_master_get_parent,
386 .set_parent = clk_sama7g5_master_set_parent,
387};
388
389struct clk_hw * __init
390at91_clk_sama7g5_register_master(struct regmap *regmap,
391 const char *name, int num_parents,
392 const char **parent_names,
393 u32 *mux_table,
394 spinlock_t *lock, u8 id,
395 bool critical, int chg_pid)
396{
397 struct clk_master *master;
398 struct clk_hw *hw;
399 struct clk_init_data init;
400 unsigned long flags;
401 unsigned int val;
402 int ret;
403
404 if (!name || !num_parents || !parent_names || !mux_table ||
405 !lock || id > MASTER_MAX_ID)
406 return ERR_PTR(-EINVAL);
407
408 master = kzalloc(sizeof(*master), GFP_KERNEL);
409 if (!master)
410 return ERR_PTR(-ENOMEM);
411
412 init.name = name;
413 init.ops = &sama7g5_master_ops;
414 init.parent_names = parent_names;
415 init.num_parents = num_parents;
416 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
417 if (chg_pid >= 0)
418 init.flags |= CLK_SET_RATE_PARENT;
419 if (critical)
420 init.flags |= CLK_IS_CRITICAL;
421
422 master->hw.init = &init;
423 master->regmap = regmap;
424 master->id = id;
425 master->chg_pid = chg_pid;
426 master->lock = lock;
427 master->mux_table = mux_table;
428
429 spin_lock_irqsave(master->lock, flags);
430 regmap_write(master->regmap, PMC_MCR, master->id);
431 regmap_read(master->regmap, PMC_MCR, &val);
432 master->parent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
433 master->div = (val & PMC_MCR_DIV) >> MASTER_DIV_SHIFT;
434 spin_unlock_irqrestore(master->lock, flags);
435
436 hw = &master->hw;
437 ret = clk_hw_register(NULL, &master->hw);
438 if (ret) {
439 kfree(master);
440 hw = ERR_PTR(ret);
441 }
442
443 return hw;
444}
445
146const struct clk_master_layout at91rm9200_master_layout = {446const struct clk_master_layout at91rm9200_master_layout = {
147 .mask = 0x31F,447 .mask = 0x31F,
148 .pres_shift = 2,448 .pres_shift = 2,
drivers/clk/at91/clk-peripheral.c+105−6
@@ -38,6 +38,7 @@ struct clk_sam9x5_peripheral { · 37 unmodified lines
38 u32 div;38 u32 div;
39 const struct clk_pcr_layout *layout;39 const struct clk_pcr_layout *layout;
40 bool auto_div;40 bool auto_div;
41 int chg_pid;
41};42};
42 43
43#define to_clk_sam9x5_peripheral(hw) \44#define to_clk_sam9x5_peripheral(hw) \
@@ -208,7 +209,7 @@ static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) · 164 unmodified lines
208 regmap_read(periph->regmap, periph->layout->offset, &status);209 regmap_read(periph->regmap, periph->layout->offset, &status);
209 spin_unlock_irqrestore(periph->lock, flags);210 spin_unlock_irqrestore(periph->lock, flags);
210 211
211 return status & AT91_PMC_PCR_EN ? 1 : 0;212 return !!(status & AT91_PMC_PCR_EN);
212}213}
213 214
214static unsigned long215static unsigned long
@@ -238,6 +239,87 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, · 23 unmodified lines
238 return parent_rate >> periph->div;239 return parent_rate >> periph->div;
239}240}
240 241
242static void clk_sam9x5_peripheral_best_diff(struct clk_rate_request *req,
243 struct clk_hw *parent,
244 unsigned long parent_rate,
245 u32 shift, long *best_diff,
246 long *best_rate)
247{
248 unsigned long tmp_rate = parent_rate >> shift;
249 unsigned long tmp_diff = abs(req->rate - tmp_rate);
250
251 if (*best_diff < 0 || *best_diff >= tmp_diff) {
252 *best_rate = tmp_rate;
253 *best_diff = tmp_diff;
254 req->best_parent_rate = parent_rate;
255 req->best_parent_hw = parent;
256 }
257}
258
259static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
260 struct clk_rate_request *req)
261{
262 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
263 struct clk_hw *parent = clk_hw_get_parent(hw);
264 struct clk_rate_request req_parent = *req;
265 unsigned long parent_rate = clk_hw_get_rate(parent);
266 unsigned long tmp_rate;
267 long best_rate = LONG_MIN;
268 long best_diff = LONG_MIN;
269 u32 shift;
270
271 if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
272 return parent_rate;
273
274 /* Fist step: check the available dividers. */
275 for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
276 tmp_rate = parent_rate >> shift;
277
278 if (periph->range.max && tmp_rate > periph->range.max)
279 continue;
280
281 clk_sam9x5_peripheral_best_diff(req, parent, parent_rate,
282 shift, &best_diff, &best_rate);
283
284 if (!best_diff || best_rate <= req->rate)
285 break;
286 }
287
288 if (periph->chg_pid < 0)
289 goto end;
290
291 /* Step two: try to request rate from parent. */
292 parent = clk_hw_get_parent_by_index(hw, periph->chg_pid);
293 if (!parent)
294 goto end;
295
296 for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
297 req_parent.rate = req->rate << shift;
298
299 if (__clk_determine_rate(parent, &req_parent))
300 continue;
301
302 clk_sam9x5_peripheral_best_diff(req, parent, req_parent.rate,
303 shift, &best_diff, &best_rate);
304
305 if (!best_diff)
306 break;
307 }
308end:
309 if (best_rate < 0 ||
310 (periph->range.max && best_rate > periph->range.max))
311 return -EINVAL;
312
313 pr_debug("PCK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
314 __func__, best_rate,
315 __clk_get_name((req->best_parent_hw)->clk),
316 req->best_parent_rate);
317
318 req->rate = best_rate;
319
320 return 0;
321}
322
241static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,323static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
242 unsigned long rate,324 unsigned long rate,
243 unsigned long *parent_rate)325 unsigned long *parent_rate)
@@ -320,11 +402,21 @@ static const struct clk_ops sam9x5_peripheral_ops = { · 76 unmodified lines
320 .set_rate = clk_sam9x5_peripheral_set_rate,402 .set_rate = clk_sam9x5_peripheral_set_rate,
321};403};
322 404
405static const struct clk_ops sam9x5_peripheral_chg_ops = {
406 .enable = clk_sam9x5_peripheral_enable,
407 .disable = clk_sam9x5_peripheral_disable,
408 .is_enabled = clk_sam9x5_peripheral_is_enabled,
409 .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
410 .determine_rate = clk_sam9x5_peripheral_determine_rate,
411 .set_rate = clk_sam9x5_peripheral_set_rate,
412};
413
323struct clk_hw * __init414struct clk_hw * __init
324at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,415at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
325 const struct clk_pcr_layout *layout,416 const struct clk_pcr_layout *layout,
326 const char *name, const char *parent_name,417 const char *name, const char *parent_name,
327 u32 id, const struct clk_range *range)418 u32 id, const struct clk_range *range,
419 int chg_pid)
328{420{
329 struct clk_sam9x5_peripheral *periph;421 struct clk_sam9x5_peripheral *periph;
330 struct clk_init_data init;422 struct clk_init_data init;
@@ -339,10 +431,16 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, · 8 unmodified lines
339 return ERR_PTR(-ENOMEM);431 return ERR_PTR(-ENOMEM);
340 432
341 init.name = name;433 init.name = name;
342 init.ops = &sam9x5_peripheral_ops;434 init.parent_names = &parent_name;
343 init.parent_names = (parent_name ? &parent_name : NULL);435 init.num_parents = 1;
344 init.num_parents = (parent_name ? 1 : 0);436 if (chg_pid < 0) {
345 init.flags = 0;437 init.flags = 0;
438 init.ops = &sam9x5_peripheral_ops;
439 } else {
440 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
441 CLK_SET_RATE_PARENT;
442 init.ops = &sam9x5_peripheral_chg_ops;
443 }
346 444
347 periph->id = id;445 periph->id = id;
348 periph->hw.init = &init;446 periph->hw.init = &init;
@@ -353,6 +451,7 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, · 4 unmodified lines
353 periph->auto_div = true;451 periph->auto_div = true;
354 periph->layout = layout;452 periph->layout = layout;
355 periph->range = *range;453 periph->range = *range;
454 periph->chg_pid = chg_pid;
356 455
357 hw = &periph->hw;456 hw = &periph->hw;
358 ret = clk_hw_register(NULL, &periph->hw);457 ret = clk_hw_register(NULL, &periph->hw);
drivers/clk/at91/clk-programmable.c+10−1
@@ -21,6 +21,7 @@ · 20 unmodified lines
21struct clk_programmable {21struct clk_programmable {
22 struct clk_hw hw;22 struct clk_hw hw;
23 struct regmap *regmap;23 struct regmap *regmap;
24 u32 *mux_table;
24 u8 id;25 u8 id;
25 const struct clk_programmable_layout *layout;26 const struct clk_programmable_layout *layout;
26};27};
@@ -108,6 +109,9 @@ static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) · 81 unmodified lines
108 if (layout->have_slck_mck)109 if (layout->have_slck_mck)
109 mask |= AT91_PMC_CSSMCK_MCK;110 mask |= AT91_PMC_CSSMCK_MCK;
110 111
112 if (prog->mux_table)
113 pckr = clk_mux_index_to_val(prog->mux_table, 0, index);
114
111 if (index > layout->css_mask) {115 if (index > layout->css_mask) {
112 if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck)116 if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck)
113 return -EINVAL;117 return -EINVAL;
@@ -134,6 +138,9 @@ static u8 clk_programmable_get_parent(struct clk_hw *hw) · 20 unmodified lines
134 if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret)138 if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret)
135 ret = PROG_MAX_RM9200_CSS + 1;139 ret = PROG_MAX_RM9200_CSS + 1;
136 140
141 if (prog->mux_table)
142 ret = clk_mux_val_to_index(&prog->hw, prog->mux_table, 0, ret);
143
137 return ret;144 return ret;
138}145}
139 146
@@ -182,7 +189,8 @@ struct clk_hw * __init · 42 unmodified lines
182at91_clk_register_programmable(struct regmap *regmap,189at91_clk_register_programmable(struct regmap *regmap,
183 const char *name, const char **parent_names,190 const char *name, const char **parent_names,
184 u8 num_parents, u8 id,191 u8 num_parents, u8 id,
185 const struct clk_programmable_layout *layout)192 const struct clk_programmable_layout *layout,
193 u32 *mux_table)
186{194{
187 struct clk_programmable *prog;195 struct clk_programmable *prog;
188 struct clk_hw *hw;196 struct clk_hw *hw;
@@ -206,6 +214,7 @@ at91_clk_register_programmable(struct regmap *regmap, · 17 unmodified lines
206 prog->layout = layout;214 prog->layout = layout;
207 prog->hw.init = &init;215 prog->hw.init = &init;
208 prog->regmap = regmap;216 prog->regmap = regmap;
217 prog->mux_table = mux_table;
209 218
210 hw = &prog->hw;219 hw = &prog->hw;
211 ret = clk_hw_register(NULL, &prog->hw);220 ret = clk_hw_register(NULL, &prog->hw);
drivers/clk/at91/clk-sam9x60-pll.c+381−166
@@ -15,26 +15,41 @@ · 14 unmodified lines
15#include "pmc.h"15#include "pmc.h"
16 16
17#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)17#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
18#define PMC_PLL_CTRL1_MUL_MSK GENMASK(30, 24)18#define PMC_PLL_CTRL1_MUL_MSK GENMASK(31, 24)
19#define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
19 20
20#define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)21#define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
21#define UPLL_DIV 222#define UPLL_DIV 2
22#define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)23#define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
23 24
24#define PLL_MAX_ID 125#define FCORE_MIN (600000000)
26#define FCORE_MAX (1200000000)
25 27
26struct sam9x60_pll {28#define PLL_MAX_ID 7
27 struct clk_hw hw;29
30struct sam9x60_pll_core {
28 struct regmap *regmap;31 struct regmap *regmap;
29 spinlock_t *lock;32 spinlock_t *lock;
30 const struct clk_pll_characteristics *characteristics;33 const struct clk_pll_characteristics *characteristics;
31 u32 frac;34 const struct clk_pll_layout *layout;
35 struct clk_hw hw;
32 u8 id;36 u8 id;
33 u8 div;37};
38
39struct sam9x60_frac {
40 struct sam9x60_pll_core core;
41 u32 frac;
34 u16 mul;42 u16 mul;
35};43};
36 44
37#define to_sam9x60_pll(hw) container_of(hw, struct sam9x60_pll, hw)45struct sam9x60_div {
46 struct sam9x60_pll_core core;
47 u8 div;
48};
49
50#define to_sam9x60_pll_core(hw) container_of(hw, struct sam9x60_pll_core, hw)
51#define to_sam9x60_frac(core) container_of(core, struct sam9x60_frac, core)
52#define to_sam9x60_div(core) container_of(core, struct sam9x60_div, core)
38 53
39static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)54static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
40{55{
@@ -45,41 +60,53 @@ static inline bool sam9x60_pll_ready(struct regmap *regmap, int id) · 4 unmodified lines
45 return !!(status & BIT(id));60 return !!(status & BIT(id));
46}61}
47 62
48static int sam9x60_pll_prepare(struct clk_hw *hw)63static bool sam9x60_frac_pll_ready(struct regmap *regmap, u8 id)
49{64{
50 struct sam9x60_pll *pll = to_sam9x60_pll(hw);65 return sam9x60_pll_ready(regmap, id);
51 struct regmap *regmap = pll->regmap;66}
52 unsigned long flags;
53 u8 div;
54 u16 mul;
55 u32 val;
56 67
57 spin_lock_irqsave(pll->lock, flags);68static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw,
58 regmap_write(regmap, AT91_PMC_PLL_UPDT, pll->id);69 unsigned long parent_rate)
70{
71 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
72 struct sam9x60_frac *frac = to_sam9x60_frac(core);
59 73
60 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);74 return (parent_rate * (frac->mul + 1) +
61 div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);75 ((u64)parent_rate * frac->frac >> 22));
76}
62 77
78static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
79{
80 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
81 struct sam9x60_frac *frac = to_sam9x60_frac(core);
82 struct regmap *regmap = core->regmap;
83 unsigned int val, cfrac, cmul;
84 unsigned long flags;
85
86 spin_lock_irqsave(core->lock, flags);
87
88 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
89 AT91_PMC_PLL_UPDT_ID_MSK, core->id);
63 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);90 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
64 mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);91 cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
92 cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
65 93
66 if (sam9x60_pll_ready(regmap, pll->id) &&94 if (sam9x60_frac_pll_ready(regmap, core->id) &&
67 (div == pll->div && mul == pll->mul)) {95 (cmul == frac->mul && cfrac == frac->frac))
68 spin_unlock_irqrestore(pll->lock, flags);96 goto unlock;
69 return 0;
70 }
71 97
72 /* Recommended value for AT91_PMC_PLL_ACR */98 /* Recommended value for PMC_PLL_ACR */
73 if (pll->characteristics->upll)99 if (core->characteristics->upll)
74 val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;100 val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;
75 else101 else
76 val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;102 val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;
77 regmap_write(regmap, AT91_PMC_PLL_ACR, val);103 regmap_write(regmap, AT91_PMC_PLL_ACR, val);
78 104
79 regmap_write(regmap, AT91_PMC_PLL_CTRL1,105 regmap_write(regmap, AT91_PMC_PLL_CTRL1,
80 FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK, pll->mul));106 (frac->mul << core->layout->mul_shift) |
107 (frac->frac << core->layout->frac_shift));
81 108
82 if (pll->characteristics->upll) {109 if (core->characteristics->upll) {
83 /* Enable the UTMI internal bandgap */110 /* Enable the UTMI internal bandgap */
84 val |= AT91_PMC_PLL_ACR_UTMIBG;111 val |= AT91_PMC_PLL_ACR_UTMIBG;
85 regmap_write(regmap, AT91_PMC_PLL_ACR, val);112 regmap_write(regmap, AT91_PMC_PLL_ACR, val);
@@ -94,221 +121,409 @@ static int sam9x60_pll_prepare(struct clk_hw *hw) · 8 unmodified lines
94 }121 }
95 122
96 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,123 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
97 AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE);124 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
125 AT91_PMC_PLL_UPDT_UPDATE | core->id);
98 126
99 regmap_write(regmap, AT91_PMC_PLL_CTRL0,127 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
100 AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL |128 AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
101 AT91_PMC_PLL_CTRL0_ENPLLCK | pll->div);129 AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
102 130
103 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,131 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
104 AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE);132 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
133 AT91_PMC_PLL_UPDT_UPDATE | core->id);
105 134
106 while (!sam9x60_pll_ready(regmap, pll->id))135 while (!sam9x60_pll_ready(regmap, core->id))
107 cpu_relax();136 cpu_relax();
108 137
109 spin_unlock_irqrestore(pll->lock, flags);138unlock:
139 spin_unlock_irqrestore(core->lock, flags);
110 140
111 return 0;141 return 0;
112}142}
113 143
114static int sam9x60_pll_is_prepared(struct clk_hw *hw)144static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
115{145{
116 struct sam9x60_pll *pll = to_sam9x60_pll(hw);146 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
147 struct regmap *regmap = core->regmap;
148 unsigned long flags;
149
150 spin_lock_irqsave(core->lock, flags);
117 151
118 return sam9x60_pll_ready(pll->regmap, pll->id);152 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
153 AT91_PMC_PLL_UPDT_ID_MSK, core->id);
154
155 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL, 0);
156
157 if (core->characteristics->upll)
158 regmap_update_bits(regmap, AT91_PMC_PLL_ACR,
159 AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR, 0);
160
161 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
162 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
163 AT91_PMC_PLL_UPDT_UPDATE | core->id);
164
165 spin_unlock_irqrestore(core->lock, flags);
119}166}
120 167
121static void sam9x60_pll_unprepare(struct clk_hw *hw)168static int sam9x60_frac_pll_is_prepared(struct clk_hw *hw)
122{169{
123 struct sam9x60_pll *pll = to_sam9x60_pll(hw);170 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
124 unsigned long flags;
125 171
126 spin_lock_irqsave(pll->lock, flags);172 return sam9x60_pll_ready(core->regmap, core->id);
173}
127 174
128 regmap_write(pll->regmap, AT91_PMC_PLL_UPDT, pll->id);175static long sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core *core,
176 unsigned long rate,
177 unsigned long parent_rate,
178 bool update)
179{
180 struct sam9x60_frac *frac = to_sam9x60_frac(core);
181 unsigned long tmprate, remainder;
182 unsigned long nmul = 0;
183 unsigned long nfrac = 0;
129 184
130 regmap_update_bits(pll->regmap, AT91_PMC_PLL_CTRL0,185 if (rate < FCORE_MIN || rate > FCORE_MAX)
131 AT91_PMC_PLL_CTRL0_ENPLLCK, 0);186 return -ERANGE;
132 187
133 regmap_update_bits(pll->regmap, AT91_PMC_PLL_UPDT,188 /*
134 AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE);189 * Calculate the multiplier associated with the current
190 * divider that provide the closest rate to the requested one.
191 */
192 nmul = mult_frac(rate, 1, parent_rate);
193 tmprate = mult_frac(parent_rate, nmul, 1);
194 remainder = rate - tmprate;
135 195
136 regmap_update_bits(pll->regmap, AT91_PMC_PLL_CTRL0,196 if (remainder) {
137 AT91_PMC_PLL_CTRL0_ENPLL, 0);197 nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),
198 parent_rate);
138 199
139 if (pll->characteristics->upll)200 tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,
140 regmap_update_bits(pll->regmap, AT91_PMC_PLL_ACR,201 (1 << 22));
141 AT91_PMC_PLL_ACR_UTMIBG |202 }
142 AT91_PMC_PLL_ACR_UTMIVR, 0);
143 203
144 regmap_update_bits(pll->regmap, AT91_PMC_PLL_UPDT,204 /* Check if resulted rate is a valid. */
145 AT91_PMC_PLL_UPDT_UPDATE, AT91_PMC_PLL_UPDT_UPDATE);205 if (tmprate < FCORE_MIN || tmprate > FCORE_MAX)
206 return -ERANGE;
146 207
147 spin_unlock_irqrestore(pll->lock, flags);208 if (update) {
209 frac->mul = nmul - 1;
210 frac->frac = nfrac;
211 }
212
213 return tmprate;
148}214}
149 215
150static unsigned long sam9x60_pll_recalc_rate(struct clk_hw *hw,216static long sam9x60_frac_pll_round_rate(struct clk_hw *hw, unsigned long rate,
151 unsigned long parent_rate)217 unsigned long *parent_rate)
152{218{
153 struct sam9x60_pll *pll = to_sam9x60_pll(hw);219 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
154 220
155 return (parent_rate * (pll->mul + 1)) / (pll->div + 1);221 return sam9x60_frac_pll_compute_mul_frac(core, rate, *parent_rate, false);
156}222}
157 223
158static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll,224static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
159 unsigned long rate,225 unsigned long parent_rate)
160 unsigned long parent_rate,
161 bool update)
162{226{
163 const struct clk_pll_characteristics *characteristics =227 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
164 pll->characteristics;
165 unsigned long bestremainder = ULONG_MAX;
166 unsigned long maxdiv, mindiv, tmpdiv;
167 long bestrate = -ERANGE;
168 unsigned long bestdiv = 0;
169 unsigned long bestmul = 0;
170 unsigned long bestfrac = 0;
171 228
172 if (rate < characteristics->output[0].min ||229 return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
173 rate > characteristics->output[0].max)230}
174 return -ERANGE;
175 231
176 if (!pll->characteristics->upll) {232static const struct clk_ops sam9x60_frac_pll_ops = {
177 mindiv = parent_rate / rate;233 .prepare = sam9x60_frac_pll_prepare,
178 if (mindiv < 2)234 .unprepare = sam9x60_frac_pll_unprepare,
179 mindiv = 2;235 .is_prepared = sam9x60_frac_pll_is_prepared,
236 .recalc_rate = sam9x60_frac_pll_recalc_rate,
237 .round_rate = sam9x60_frac_pll_round_rate,
238 .set_rate = sam9x60_frac_pll_set_rate,
239};
180 240
181 maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX, rate);241static int sam9x60_div_pll_prepare(struct clk_hw *hw)
182 if (maxdiv > PLL_DIV_MAX)242{
183 maxdiv = PLL_DIV_MAX;243 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
184 } else {244 struct sam9x60_div *div = to_sam9x60_div(core);
185 mindiv = maxdiv = UPLL_DIV;245 struct regmap *regmap = core->regmap;
186 }246 unsigned long flags;
247 unsigned int val, cdiv;
187 248
188 for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {249 spin_lock_irqsave(core->lock, flags);
189 unsigned long remainder;250 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
190 unsigned long tmprate;251 AT91_PMC_PLL_UPDT_ID_MSK, core->id);
191 unsigned long tmpmul;252 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
192 unsigned long tmpfrac = 0;253 cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
193 254
194 /*255 /* Stop if enabled an nothing changed. */
195 * Calculate the multiplier associated with the current256 if (!!(val & core->layout->endiv_mask) && cdiv == div->div)
196 * divider that provide the closest rate to the requested one.257 goto unlock;
197 */
198 tmpmul = mult_frac(rate, tmpdiv, parent_rate);
199 tmprate = mult_frac(parent_rate, tmpmul, tmpdiv);
200 remainder = rate - tmprate;
201 258
202 if (remainder) {259 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
203 tmpfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * tmpdiv * (1 << 22),260 core->layout->div_mask | core->layout->endiv_mask,
204 parent_rate);261 (div->div << core->layout->div_shift) |
262 (1 << core->layout->endiv_shift));
205 263
206 tmprate += DIV_ROUND_CLOSEST_ULL((u64)tmpfrac * parent_rate,264 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
207 tmpdiv * (1 << 22));265 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
266 AT91_PMC_PLL_UPDT_UPDATE | core->id);
208 267
209 if (tmprate > rate)268 while (!sam9x60_pll_ready(regmap, core->id))
210 remainder = tmprate - rate;269 cpu_relax();
211 else
212 remainder = rate - tmprate;
213 }
214 270
215 /*271unlock:
216 * Compare the remainder with the best remainder found until272 spin_unlock_irqrestore(core->lock, flags);
217 * now and elect a new best multiplier/divider pair if the273
218 * current remainder is smaller than the best one.274 return 0;
219 */275}
220 if (remainder < bestremainder) {276
221 bestremainder = remainder;277static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
222 bestdiv = tmpdiv;278{
223 bestmul = tmpmul;279 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
224 bestrate = tmprate;280 struct regmap *regmap = core->regmap;
225 bestfrac = tmpfrac;281 unsigned long flags;
282
283 spin_lock_irqsave(core->lock, flags);
284
285 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
286 AT91_PMC_PLL_UPDT_ID_MSK, core->id);
287
288 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
289 core->layout->endiv_mask, 0);
290
291 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
292 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
293 AT91_PMC_PLL_UPDT_UPDATE | core->id);
294
295 spin_unlock_irqrestore(core->lock, flags);
296}
297
298static int sam9x60_div_pll_is_prepared(struct clk_hw *hw)
299{
300 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
301 struct regmap *regmap = core->regmap;
302 unsigned long flags;
303 unsigned int val;
304
305 spin_lock_irqsave(core->lock, flags);
306
307 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
308 AT91_PMC_PLL_UPDT_ID_MSK, core->id);
309 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
310
311 spin_unlock_irqrestore(core->lock, flags);
312
313 return !!(val & core->layout->endiv_mask);
314}
315
316static unsigned long sam9x60_div_pll_recalc_rate(struct clk_hw *hw,
317 unsigned long parent_rate)
318{
319 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
320 struct sam9x60_div *div = to_sam9x60_div(core);
321
322 return DIV_ROUND_CLOSEST_ULL(parent_rate, (div->div + 1));
323}
324
325static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
326 unsigned long *parent_rate,
327 unsigned long rate)
328{
329 const struct clk_pll_characteristics *characteristics =
330 core->characteristics;
331 struct clk_hw *parent = clk_hw_get_parent(&core->hw);
332 unsigned long tmp_rate, tmp_parent_rate, tmp_diff;
333 long best_diff = -1, best_rate = -EINVAL;
334 u32 divid, best_div;
335
336 if (!rate)
337 return 0;
338
339 if (rate < characteristics->output[0].min ||
340 rate > characteristics->output[0].max)
341 return -ERANGE;
342
343 for (divid = 1; divid < core->layout->div_mask; divid++) {
344 tmp_parent_rate = clk_hw_round_rate(parent, rate * divid);
345 if (!tmp_parent_rate)
346 continue;
347
348 tmp_rate = DIV_ROUND_CLOSEST_ULL(tmp_parent_rate, divid);
349 tmp_diff = abs(rate - tmp_rate);
350
351 if (best_diff < 0 || best_diff > tmp_diff) {
352 *parent_rate = tmp_parent_rate;
353 best_rate = tmp_rate;
354 best_diff = tmp_diff;
355 best_div = divid;
226 }356 }
227 357
228 /* We've found a perfect match! */358 if (!best_diff)
229 if (!remainder)
230 break;359 break;
231 }360 }
232 361
233 /* Check if bestrate is a valid output rate */362 if (best_rate < characteristics->output[0].min ||
234 if (bestrate < characteristics->output[0].min &&363 best_rate > characteristics->output[0].max)
235 bestrate > characteristics->output[0].max)
236 return -ERANGE;364 return -ERANGE;
237 365
238 if (update) {366 return best_rate;
239 pll->div = bestdiv - 1;
240 pll->mul = bestmul - 1;
241 pll->frac = bestfrac;
242 }
243
244 return bestrate;
245}367}
246 368
247static long sam9x60_pll_round_rate(struct clk_hw *hw, unsigned long rate,369static long sam9x60_div_pll_round_rate(struct clk_hw *hw, unsigned long rate,
248 unsigned long *parent_rate)370 unsigned long *parent_rate)
249{371{
250 struct sam9x60_pll *pll = to_sam9x60_pll(hw);372 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
251 373
252 return sam9x60_pll_get_best_div_mul(pll, rate, *parent_rate, false);374 return sam9x60_div_pll_compute_div(core, parent_rate, rate);
253}375}
254 376
255static int sam9x60_pll_set_rate(struct clk_hw *hw, unsigned long rate,377static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
256 unsigned long parent_rate)378 unsigned long parent_rate)
257{379{
258 struct sam9x60_pll *pll = to_sam9x60_pll(hw);380 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
381 struct sam9x60_div *div = to_sam9x60_div(core);
382
383 div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
259 384
260 return sam9x60_pll_get_best_div_mul(pll, rate, parent_rate, true);385 return 0;
261}386}
262 387
263static const struct clk_ops pll_ops = {388static const struct clk_ops sam9x60_div_pll_ops = {
264 .prepare = sam9x60_pll_prepare,389 .prepare = sam9x60_div_pll_prepare,
265 .unprepare = sam9x60_pll_unprepare,390 .unprepare = sam9x60_div_pll_unprepare,
266 .is_prepared = sam9x60_pll_is_prepared,391 .is_prepared = sam9x60_div_pll_is_prepared,
267 .recalc_rate = sam9x60_pll_recalc_rate,392 .recalc_rate = sam9x60_div_pll_recalc_rate,
268 .round_rate = sam9x60_pll_round_rate,393 .round_rate = sam9x60_div_pll_round_rate,
269 .set_rate = sam9x60_pll_set_rate,394 .set_rate = sam9x60_div_pll_set_rate,
270};395};
271 396
272struct clk_hw * __init397struct clk_hw * __init
273sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock,398sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
274 const char *name, const char *parent_name, u8 id,399 const char *name, const char *parent_name,
275 const struct clk_pll_characteristics *characteristics)400 struct clk_hw *parent_hw, u8 id,
401 const struct clk_pll_characteristics *characteristics,
402 const struct clk_pll_layout *layout, bool critical)
276{403{
277 struct sam9x60_pll *pll;404 struct sam9x60_frac *frac;
278 struct clk_hw *hw;405 struct clk_hw *hw;
279 struct clk_init_data init;406 struct clk_init_data init;
280 unsigned int pllr;407 unsigned long parent_rate, flags;
408 unsigned int val;
281 int ret;409 int ret;
282 410
283 if (id > PLL_MAX_ID)411 if (id > PLL_MAX_ID || !lock || !parent_hw)
284 return ERR_PTR(-EINVAL);412 return ERR_PTR(-EINVAL);
285 413
286 pll = kzalloc(sizeof(*pll), GFP_KERNEL);414 frac = kzalloc(sizeof(*frac), GFP_KERNEL);
287 if (!pll)415 if (!frac)
288 return ERR_PTR(-ENOMEM);416 return ERR_PTR(-ENOMEM);
289 417
290 init.name = name;418 init.name = name;
291 init.ops = &pll_ops;
292 init.parent_names = &parent_name;419 init.parent_names = &parent_name;
293 init.num_parents = 1;420 init.num_parents = 1;
421 init.ops = &sam9x60_frac_pll_ops;
294 init.flags = CLK_SET_RATE_GATE;422 init.flags = CLK_SET_RATE_GATE;
423 if (critical)
424 init.flags |= CLK_IS_CRITICAL;
425
426 frac->core.id = id;
427 frac->core.hw.init = &init;
428 frac->core.characteristics = characteristics;
429 frac->core.layout = layout;
430 frac->core.regmap = regmap;
431 frac->core.lock = lock;
432
433 spin_lock_irqsave(frac->core.lock, flags);
434 if (sam9x60_pll_ready(regmap, id)) {
435 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
436 AT91_PMC_PLL_UPDT_ID_MSK, id);
437 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
438 frac->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
439 frac->frac = FIELD_GET(PMC_PLL_CTRL1_FRACR_MSK, val);
440 } else {
441 /*
442 * This means the PLL is not setup by bootloaders. In this
443 * case we need to set the minimum rate for it. Otherwise
444 * a clock child of this PLL may be enabled before setting
445 * its rate leading to enabling this PLL with unsupported
446 * rate. This will lead to PLL not being locked at all.
447 */
448 parent_rate = clk_hw_get_rate(parent_hw);
449 if (!parent_rate) {
450 hw = ERR_PTR(-EINVAL);
451 goto free;
452 }
453
454 ret = sam9x60_frac_pll_compute_mul_frac(&frac->core, FCORE_MIN,
455 parent_rate, true);
456 if (ret <= 0) {
457 hw = ERR_PTR(ret);
458 goto free;
459 }
460 }
461 spin_unlock_irqrestore(frac->core.lock, flags);
462
463 hw = &frac->core.hw;
464 ret = clk_hw_register(NULL, hw);
465 if (ret) {
466 kfree(frac);
467 hw = ERR_PTR(ret);
468 }
295 469
296 pll->id = id;470 return hw;
297 pll->hw.init = &init;471
298 pll->characteristics = characteristics;472free:
299 pll->regmap = regmap;473 spin_unlock_irqrestore(frac->core.lock, flags);
300 pll->lock = lock;474 kfree(frac);
475 return hw;
476}
477
478struct clk_hw * __init
479sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
480 const char *name, const char *parent_name, u8 id,
481 const struct clk_pll_characteristics *characteristics,
482 const struct clk_pll_layout *layout, bool critical)
483{
484 struct sam9x60_div *div;
485 struct clk_hw *hw;
486 struct clk_init_data init;
487 unsigned long flags;
488 unsigned int val;
489 int ret;
490
491 if (id > PLL_MAX_ID || !lock)
492 return ERR_PTR(-EINVAL);
493
494 div = kzalloc(sizeof(*div), GFP_KERNEL);
495 if (!div)
496 return ERR_PTR(-ENOMEM);
497
498 init.name = name;
499 init.parent_names = &parent_name;
500 init.num_parents = 1;
501 init.ops = &sam9x60_div_pll_ops;
502 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
503 CLK_SET_RATE_PARENT;
504 if (critical)
505 init.flags |= CLK_IS_CRITICAL;
506
507 div->core.id = id;
508 div->core.hw.init = &init;
509 div->core.characteristics = characteristics;
510 div->core.layout = layout;
511 div->core.regmap = regmap;
512 div->core.lock = lock;
513
514 spin_lock_irqsave(div->core.lock, flags);
515
516 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
517 AT91_PMC_PLL_UPDT_ID_MSK, id);
518 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
519 div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
301 520
302 regmap_write(regmap, AT91_PMC_PLL_UPDT, id);521 spin_unlock_irqrestore(div->core.lock, flags);
303 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &pllr);
304 pll->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, pllr);
305 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &pllr);
306 pll->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, pllr);
307 522
308 hw = &pll->hw;523 hw = &div->core.hw;
309 ret = clk_hw_register(NULL, hw);524 ret = clk_hw_register(NULL, hw);
310 if (ret) {525 if (ret) {
311 kfree(pll);526 kfree(div);
312 hw = ERR_PTR(ret);527 hw = ERR_PTR(ret);
313 }528 }
314 529
drivers/clk/at91/clk-system.c+2−2
@@ -34,7 +34,7 @@ static inline bool clk_system_ready(struct regmap *regmap, int id) · 33 unmodified lines
34 34
35 regmap_read(regmap, AT91_PMC_SR, &status);35 regmap_read(regmap, AT91_PMC_SR, &status);
36 36
37 return status & (1 << id) ? 1 : 0;37 return !!(status & (1 << id));
38}38}
39 39
40static int clk_system_prepare(struct clk_hw *hw)40static int clk_system_prepare(struct clk_hw *hw)
@@ -74,7 +74,7 @@ static int clk_system_is_prepared(struct clk_hw *hw) · 33 unmodified lines
74 74
75 regmap_read(sys->regmap, AT91_PMC_SR, &status);75 regmap_read(sys->regmap, AT91_PMC_SR, &status);
76 76
77 return status & (1 << sys->id) ? 1 : 0;77 return !!(status & (1 << sys->id));
78}78}
79 79
80static const struct clk_ops system_ops = {80static const struct clk_ops system_ops = {
drivers/clk/at91/clk-utmi.c+98−5
@@ -120,9 +120,11 @@ static const struct clk_ops utmi_ops = { · 119 unmodified lines
120 .recalc_rate = clk_utmi_recalc_rate,120 .recalc_rate = clk_utmi_recalc_rate,
121};121};
122 122
123struct clk_hw * __init123static struct clk_hw * __init
124at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,124at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
125 const char *name, const char *parent_name)125 struct regmap *regmap_sfr,
126 const char *name, const char *parent_name,
127 const struct clk_ops *ops, unsigned long flags)
126{128{
127 struct clk_utmi *utmi;129 struct clk_utmi *utmi;
128 struct clk_hw *hw;130 struct clk_hw *hw;
@@ -134,10 +136,10 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, · 5 unmodified lines
134 return ERR_PTR(-ENOMEM);136 return ERR_PTR(-ENOMEM);
135 137
136 init.name = name;138 init.name = name;
137 init.ops = &utmi_ops;139 init.ops = ops;
138 init.parent_names = parent_name ? &parent_name : NULL;140 init.parent_names = parent_name ? &parent_name : NULL;
139 init.num_parents = parent_name ? 1 : 0;141 init.num_parents = parent_name ? 1 : 0;
140 init.flags = CLK_SET_RATE_GATE;142 init.flags = flags;
141 143
142 utmi->hw.init = &init;144 utmi->hw.init = &init;
143 utmi->regmap_pmc = regmap_pmc;145 utmi->regmap_pmc = regmap_pmc;
@@ -152,3 +154,94 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, · 8 unmodified lines
152 154
153 return hw;155 return hw;
154}156}
157
158struct clk_hw * __init
159at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
160 const char *name, const char *parent_name)
161{
162 return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name,
163 parent_name, &utmi_ops, CLK_SET_RATE_GATE);
164}
165
166static int clk_utmi_sama7g5_prepare(struct clk_hw *hw)
167{
168 struct clk_utmi *utmi = to_clk_utmi(hw);
169 struct clk_hw *hw_parent;
170 unsigned long parent_rate;
171 unsigned int val;
172
173 hw_parent = clk_hw_get_parent(hw);
174 parent_rate = clk_hw_get_rate(hw_parent);
175
176 switch (parent_rate) {
177 case 16000000:
178 val = 0;
179 break;
180 case 20000000:
181 val = 2;
182 break;
183 case 24000000:
184 val = 3;
185 break;
186 case 32000000:
187 val = 5;
188 break;
189 default:
190 pr_err("UTMICK: unsupported main_xtal rate\n");
191 return -EINVAL;
192 }
193
194 regmap_write(utmi->regmap_pmc, AT91_PMC_XTALF, val);
195
196 return 0;
197
198}
199
200static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw)
201{
202 struct clk_utmi *utmi = to_clk_utmi(hw);
203 struct clk_hw *hw_parent;
204 unsigned long parent_rate;
205 unsigned int val;
206
207 hw_parent = clk_hw_get_parent(hw);
208 parent_rate = clk_hw_get_rate(hw_parent);
209
210 regmap_read(utmi->regmap_pmc, AT91_PMC_XTALF, &val);
211 switch (val & 0x7) {
212 case 0:
213 if (parent_rate == 16000000)
214 return 1;
215 break;
216 case 2:
217 if (parent_rate == 20000000)
218 return 1;
219 break;
220 case 3:
221 if (parent_rate == 24000000)
222 return 1;
223 break;
224 case 5:
225 if (parent_rate == 32000000)
226 return 1;
227 break;
228 default:
229 break;
230 }
231
232 return 0;
233}
234
235static const struct clk_ops sama7g5_utmi_ops = {
236 .prepare = clk_utmi_sama7g5_prepare,
237 .is_prepared = clk_utmi_sama7g5_is_prepared,
238 .recalc_rate = clk_utmi_recalc_rate,
239};
240
241struct clk_hw * __init
242at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name,
243 const char *parent_name)
244{
245 return at91_clk_register_utmi_internal(regmap_pmc, NULL, name,
246 parent_name, &sama7g5_utmi_ops, 0);
247}
drivers/clk/at91/dt-compat.c+15−10
@@ -22,6 +22,8 @@ · 21 unmodified lines
22 22
23#define SYSTEM_MAX_ID 3123#define SYSTEM_MAX_ID 31
24 24
25#define GCK_INDEX_DT_AUDIO_PLL 5
26
25#ifdef CONFIG_HAVE_AT91_AUDIO_PLL27#ifdef CONFIG_HAVE_AT91_AUDIO_PLL
26static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)28static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
27{29{
@@ -135,7 +137,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) · 107 unmodified lines
135 return;137 return;
136 138
137 for_each_child_of_node(np, gcknp) {139 for_each_child_of_node(np, gcknp) {
138 bool pll_audio = false;140 int chg_pid = INT_MIN;
139 141
140 if (of_property_read_u32(gcknp, "reg", &id))142 if (of_property_read_u32(gcknp, "reg", &id))
141 continue;143 continue;
@@ -152,12 +154,13 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) · 10 unmodified lines
152 if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&154 if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
153 (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||155 (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
154 id == GCK_ID_CLASSD))156 id == GCK_ID_CLASSD))
155 pll_audio = true;157 chg_pid = GCK_INDEX_DT_AUDIO_PLL;
156 158
157 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,159 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
158 &dt_pcr_layout, name,160 &dt_pcr_layout, name,
159 parent_names, num_parents,161 parent_names, NULL,
160 id, pll_audio, &range);162 num_parents, id, &range,
163 chg_pid);
161 if (IS_ERR(hw))164 if (IS_ERR(hw))
162 continue;165 continue;
163 166
@@ -460,7 +463,8 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type) · 296 unmodified lines
460 &dt_pcr_layout,463 &dt_pcr_layout,
461 name,464 name,
462 parent_name,465 parent_name,
463 id, &range);466 id, &range,
467 INT_MIN);
464 }468 }
465 469
466 if (IS_ERR(hw))470 if (IS_ERR(hw))
@@ -673,7 +677,8 @@ CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv", · 206 unmodified lines
673 677
674static void __init678static void __init
675of_at91_clk_prog_setup(struct device_node *np,679of_at91_clk_prog_setup(struct device_node *np,
676 const struct clk_programmable_layout *layout)680 const struct clk_programmable_layout *layout,
681 u32 *mux_table)
677{682{
678 int num;683 int num;
679 u32 id;684 u32 id;
@@ -707,7 +712,7 @@ of_at91_clk_prog_setup(struct device_node *np, · 27 unmodified lines
707 712
708 hw = at91_clk_register_programmable(regmap, name,713 hw = at91_clk_register_programmable(regmap, name,
709 parent_names, num_parents,714 parent_names, num_parents,
710 id, layout);715 id, layout, mux_table);
711 if (IS_ERR(hw))716 if (IS_ERR(hw))
712 continue;717 continue;
713 718
@@ -717,21 +722,21 @@ of_at91_clk_prog_setup(struct device_node *np, · 3 unmodified lines
717 722
718static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)723static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
719{724{
720 of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);725 of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout, NULL);
721}726}
722CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",727CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
723 of_at91rm9200_clk_prog_setup);728 of_at91rm9200_clk_prog_setup);
724 729
725static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)730static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
726{731{
727 of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);732 of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout, NULL);
728}733}
729CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",734CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
730 of_at91sam9g45_clk_prog_setup);735 of_at91sam9g45_clk_prog_setup);
731 736
732static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)737static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
733{738{
734 of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);739 of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout, NULL);
735}740}
736CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",741CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
737 of_at91sam9x5_clk_prog_setup);742 of_at91sam9x5_clk_prog_setup);
drivers/clk/at91/pmc.h+35−8
@@ -54,8 +54,14 @@ struct clk_master_characteristics { · 53 unmodified lines
54 54
55struct clk_pll_layout {55struct clk_pll_layout {
56 u32 pllr_mask;56 u32 pllr_mask;
57 u16 mul_mask;57 u32 mul_mask;
58 u32 frac_mask;
59 u32 div_mask;
60 u32 endiv_mask;
58 u8 mul_shift;61 u8 mul_shift;
62 u8 frac_shift;
63 u8 div_shift;
64 u8 endiv_shift;
59};65};
60 66
61extern const struct clk_pll_layout at91rm9200_pll_layout;67extern const struct clk_pll_layout at91rm9200_pll_layout;
@@ -122,8 +128,8 @@ struct clk_hw * __init · 60 unmodified lines
122at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,128at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
123 const struct clk_pcr_layout *layout,129 const struct clk_pcr_layout *layout,
124 const char *name, const char **parent_names,130 const char *name, const char **parent_names,
125 u8 num_parents, u8 id, bool pll_audio,131 u32 *mux_table, u8 num_parents, u8 id,
126 const struct clk_range *range);132 const struct clk_range *range, int chg_pid);
127 133
128struct clk_hw * __init134struct clk_hw * __init
129at91_clk_register_h32mx(struct regmap *regmap, const char *name,135at91_clk_register_h32mx(struct regmap *regmap, const char *name,
@@ -154,6 +160,13 @@ at91_clk_register_master(struct regmap *regmap, const char *name, · 24 unmodified lines
154 const struct clk_master_layout *layout,160 const struct clk_master_layout *layout,
155 const struct clk_master_characteristics *characteristics);161 const struct clk_master_characteristics *characteristics);
156 162
163struct clk_hw * __init
164at91_clk_sama7g5_register_master(struct regmap *regmap,
165 const char *name, int num_parents,
166 const char **parent_names, u32 *mux_table,
167 spinlock_t *lock, u8 id, bool critical,
168 int chg_pid);
169
157struct clk_hw * __init170struct clk_hw * __init
158at91_clk_register_peripheral(struct regmap *regmap, const char *name,171at91_clk_register_peripheral(struct regmap *regmap, const char *name,
159 const char *parent_name, u32 id);172 const char *parent_name, u32 id);
@@ -161,7 +174,8 @@ struct clk_hw * __init · 1 unmodified line
161at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,174at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
162 const struct clk_pcr_layout *layout,175 const struct clk_pcr_layout *layout,
163 const char *name, const char *parent_name,176 const char *name, const char *parent_name,
164 u32 id, const struct clk_range *range);177 u32 id, const struct clk_range *range,
178 int chg_pid);
165 179
166struct clk_hw * __init180struct clk_hw * __init
167at91_clk_register_pll(struct regmap *regmap, const char *name,181at91_clk_register_pll(struct regmap *regmap, const char *name,
@@ -173,14 +187,23 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name, · 5 unmodified lines
173 const char *parent_name);187 const char *parent_name);
174 188
175struct clk_hw * __init189struct clk_hw * __init
176sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock,190sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
177 const char *name, const char *parent_name, u8 id,191 const char *name, const char *parent_name, u8 id,
178 const struct clk_pll_characteristics *characteristics);192 const struct clk_pll_characteristics *characteristics,
193 const struct clk_pll_layout *layout, bool critical);
194
195struct clk_hw * __init
196sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
197 const char *name, const char *parent_name,
198 struct clk_hw *parent_hw, u8 id,
199 const struct clk_pll_characteristics *characteristics,
200 const struct clk_pll_layout *layout, bool critical);
179 201
180struct clk_hw * __init202struct clk_hw * __init
181at91_clk_register_programmable(struct regmap *regmap, const char *name,203at91_clk_register_programmable(struct regmap *regmap, const char *name,
182 const char **parent_names, u8 num_parents, u8 id,204 const char **parent_names, u8 num_parents, u8 id,
183 const struct clk_programmable_layout *layout);205 const struct clk_programmable_layout *layout,
206 u32 *mux_table);
184 207
185struct clk_hw * __init208struct clk_hw * __init
186at91_clk_register_sam9260_slow(struct regmap *regmap,209at91_clk_register_sam9260_slow(struct regmap *regmap,
@@ -213,6 +236,10 @@ struct clk_hw * __init · 26 unmodified lines
213at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,236at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
214 const char *name, const char *parent_name);237 const char *name, const char *parent_name);
215 238
239struct clk_hw * __init
240at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name,
241 const char *parent_name);
242
216#ifdef CONFIG_PM243#ifdef CONFIG_PM
217void pmc_register_id(u8 id);244void pmc_register_id(u8 id);
218void pmc_register_pck(u8 pck);245void pmc_register_pck(u8 pck);
drivers/clk/at91/sam9x60.c+49−17
@@ -22,7 +22,7 @@ static const struct clk_master_layout sam9x60_master_layout = { · 21 unmodified lines
22};22};
23 23
24static const struct clk_range plla_outputs[] = {24static const struct clk_range plla_outputs[] = {
25 { .min = 300000000, .max = 600000000 },25 { .min = 2343750, .max = 1200000000 },
26};26};
27 27
28static const struct clk_pll_characteristics plla_characteristics = {28static const struct clk_pll_characteristics plla_characteristics = {
@@ -42,6 +42,20 @@ static const struct clk_pll_characteristics upll_characteristics = { · 13 unmodified lines
42 .upll = true,42 .upll = true,
43};43};
44 44
45static const struct clk_pll_layout pll_frac_layout = {
46 .mul_mask = GENMASK(31, 24),
47 .frac_mask = GENMASK(21, 0),
48 .mul_shift = 24,
49 .frac_shift = 0,
50};
51
52static const struct clk_pll_layout pll_div_layout = {
53 .div_mask = GENMASK(7, 0),
54 .endiv_mask = BIT(29),
55 .div_shift = 0,
56 .endiv_shift = 29,
57};
58
45static const struct clk_programmable_layout sam9x60_programmable_layout = {59static const struct clk_programmable_layout sam9x60_programmable_layout = {
46 .pres_mask = 0xff,60 .pres_mask = 0xff,
47 .pres_shift = 8,61 .pres_shift = 8,
@@ -156,6 +170,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 108 unmodified lines
156 const char *td_slck_name, *md_slck_name, *mainxtal_name;170 const char *td_slck_name, *md_slck_name, *mainxtal_name;
157 struct pmc_data *sam9x60_pmc;171 struct pmc_data *sam9x60_pmc;
158 const char *parent_names[6];172 const char *parent_names[6];
173 struct clk_hw *main_osc_hw;
159 struct regmap *regmap;174 struct regmap *regmap;
160 struct clk_hw *hw;175 struct clk_hw *hw;
161 int i;176 int i;
@@ -178,7 +193,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 16 unmodified lines
178 return;193 return;
179 mainxtal_name = of_clk_get_parent_name(np, i);194 mainxtal_name = of_clk_get_parent_name(np, i);
180 195
181 regmap = syscon_node_to_regmap(np);196 regmap = device_node_to_regmap(np);
182 if (IS_ERR(regmap))197 if (IS_ERR(regmap))
183 return;198 return;
184 199
@@ -189,7 +204,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 4 unmodified lines
189 if (!sam9x60_pmc)204 if (!sam9x60_pmc)
190 return;205 return;
191 206
192 hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 24000000,207 hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
193 50000000);208 50000000);
194 if (IS_ERR(hw))209 if (IS_ERR(hw))
195 goto err_free;210 goto err_free;
@@ -200,6 +215,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 4 unmodified lines
200 bypass);215 bypass);
201 if (IS_ERR(hw))216 if (IS_ERR(hw))
202 goto err_free;217 goto err_free;
218 main_osc_hw = hw;
203 219
204 parent_names[0] = "main_rc_osc";220 parent_names[0] = "main_rc_osc";
205 parent_names[1] = "main_osc";221 parent_names[1] = "main_osc";
@@ -209,15 +225,31 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 3 unmodified lines
209 225
210 sam9x60_pmc->chws[PMC_MAIN] = hw;226 sam9x60_pmc->chws[PMC_MAIN] = hw;
211 227
212 hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "pllack",228 hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "pllack_fracck",
213 "mainck", 0, &plla_characteristics);229 "mainck", sam9x60_pmc->chws[PMC_MAIN],
230 0, &plla_characteristics,
231 &pll_frac_layout, true);
232 if (IS_ERR(hw))
233 goto err_free;
234
235 hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
236 "pllack_fracck", 0, &plla_characteristics,
237 &pll_div_layout, true);
214 if (IS_ERR(hw))238 if (IS_ERR(hw))
215 goto err_free;239 goto err_free;
216 240
217 sam9x60_pmc->chws[PMC_PLLACK] = hw;241 sam9x60_pmc->chws[PMC_PLLACK] = hw;
218 242
219 hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "upllck",243 hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "upllck_fracck",
220 "main_osc", 1, &upll_characteristics);244 "main_osc", main_osc_hw, 1,
245 &upll_characteristics,
246 &pll_frac_layout, false);
247 if (IS_ERR(hw))
248 goto err_free;
249
250 hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
251 "upllck_fracck", 1, &upll_characteristics,
252 &pll_div_layout, false);
221 if (IS_ERR(hw))253 if (IS_ERR(hw))
222 goto err_free;254 goto err_free;
223 255
@@ -225,7 +257,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 1 unmodified line
225 257
226 parent_names[0] = md_slck_name;258 parent_names[0] = md_slck_name;
227 parent_names[1] = "mainck";259 parent_names[1] = "mainck";
228 parent_names[2] = "pllack";260 parent_names[2] = "pllack_divck";
229 hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,261 hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
230 &sam9x60_master_layout,262 &sam9x60_master_layout,
231 &mck_characteristics);263 &mck_characteristics);
@@ -234,8 +266,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 2 unmodified lines
234 266
235 sam9x60_pmc->chws[PMC_MCK] = hw;267 sam9x60_pmc->chws[PMC_MCK] = hw;
236 268
237 parent_names[0] = "pllack";269 parent_names[0] = "pllack_divck";
238 parent_names[1] = "upllck";270 parent_names[1] = "upllck_divck";
239 parent_names[2] = "main_osc";271 parent_names[2] = "main_osc";
240 hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);272 hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);
241 if (IS_ERR(hw))273 if (IS_ERR(hw))
@@ -245,8 +277,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 3 unmodified lines
245 parent_names[1] = td_slck_name;277 parent_names[1] = td_slck_name;
246 parent_names[2] = "mainck";278 parent_names[2] = "mainck";
247 parent_names[3] = "masterck";279 parent_names[3] = "masterck";
248 parent_names[4] = "pllack";280 parent_names[4] = "pllack_divck";
249 parent_names[5] = "upllck";281 parent_names[5] = "upllck_divck";
250 for (i = 0; i < 8; i++) {282 for (i = 0; i < 8; i++) {
251 char name[6];283 char name[6];
252 284
@@ -254,7 +286,8 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 1 unmodified line
254 286
255 hw = at91_clk_register_programmable(regmap, name,287 hw = at91_clk_register_programmable(regmap, name,
256 parent_names, 6, i,288 parent_names, 6, i,
257 &sam9x60_programmable_layout);289 &sam9x60_programmable_layout,
290 NULL);
258 if (IS_ERR(hw))291 if (IS_ERR(hw))
259 goto err_free;292 goto err_free;
260 293
@@ -277,7 +310,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 16 unmodified lines
277 sam9x60_periphck[i].n,310 sam9x60_periphck[i].n,
278 "masterck",311 "masterck",
279 sam9x60_periphck[i].id,312 sam9x60_periphck[i].id,
280 &range);313 &range, INT_MIN);
281 if (IS_ERR(hw))314 if (IS_ERR(hw))
282 goto err_free;315 goto err_free;
283 316
@@ -288,10 +321,9 @@ static void __init sam9x60_pmc_setup(struct device_node *np) · 4 unmodified lines
288 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,321 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
289 &sam9x60_pcr_layout,322 &sam9x60_pcr_layout,
290 sam9x60_gck[i].n,323 sam9x60_gck[i].n,
291 parent_names, 6,324 parent_names, NULL, 6,
292 sam9x60_gck[i].id,325 sam9x60_gck[i].id,
293 false,326 &sam9x60_gck[i].r, INT_MIN);
294 &sam9x60_gck[i].r);
295 if (IS_ERR(hw))327 if (IS_ERR(hw))
296 goto err_free;328 goto err_free;
297 329
drivers/clk/at91/sama5d2.c+21−20
@@ -116,21 +116,20 @@ static const struct { · 115 unmodified lines
116 char *n;116 char *n;
117 u8 id;117 u8 id;
118 struct clk_range r;118 struct clk_range r;
119 bool pll;119 int chg_pid;
120} sama5d2_gck[] = {120} sama5d2_gck[] = {
121 { .n = "sdmmc0_gclk", .id = 31, },121 { .n = "sdmmc0_gclk", .id = 31, .chg_pid = INT_MIN, },
122 { .n = "sdmmc1_gclk", .id = 32, },122 { .n = "sdmmc1_gclk", .id = 32, .chg_pid = INT_MIN, },
123 { .n = "tcb0_gclk", .id = 35, .r = { .min = 0, .max = 83000000 }, },123 { .n = "tcb0_gclk", .id = 35, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
124 { .n = "tcb1_gclk", .id = 36, .r = { .min = 0, .max = 83000000 }, },124 { .n = "tcb1_gclk", .id = 36, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
125 { .n = "pwm_gclk", .id = 38, .r = { .min = 0, .max = 83000000 }, },125 { .n = "pwm_gclk", .id = 38, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
126 { .n = "isc_gclk", .id = 46, },126 { .n = "isc_gclk", .id = 46, .chg_pid = INT_MIN, },
127 { .n = "pdmic_gclk", .id = 48, },127 { .n = "pdmic_gclk", .id = 48, .chg_pid = INT_MIN, },
128 { .n = "i2s0_gclk", .id = 54, .pll = true },128 { .n = "i2s0_gclk", .id = 54, .chg_pid = 5, },
129 { .n = "i2s1_gclk", .id = 55, .pll = true },129 { .n = "i2s1_gclk", .id = 55, .chg_pid = 5, },
130 { .n = "can0_gclk", .id = 56, .r = { .min = 0, .max = 80000000 }, },130 { .n = "can0_gclk", .id = 56, .chg_pid = INT_MIN, .r = { .min = 0, .max = 80000000 }, },
131 { .n = "can1_gclk", .id = 57, .r = { .min = 0, .max = 80000000 }, },131 { .n = "can1_gclk", .id = 57, .chg_pid = INT_MIN, .r = { .min = 0, .max = 80000000 }, },
132 { .n = "classd_gclk", .id = 59, .r = { .min = 0, .max = 100000000 },132 { .n = "classd_gclk", .id = 59, .chg_pid = 5, .r = { .min = 0, .max = 100000000 }, },
133 .pll = true },
134};133};
135 134
136static const struct clk_programmable_layout sama5d2_programmable_layout = {135static const struct clk_programmable_layout sama5d2_programmable_layout = {
@@ -269,7 +268,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 132 unmodified lines
269 268
270 hw = at91_clk_register_programmable(regmap, name,269 hw = at91_clk_register_programmable(regmap, name,
271 parent_names, 6, i,270 parent_names, 6, i,
272 &sama5d2_programmable_layout);271 &sama5d2_programmable_layout,
272 NULL);
273 if (IS_ERR(hw))273 if (IS_ERR(hw))
274 goto err_free;274 goto err_free;
275 275
@@ -292,7 +292,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 16 unmodified lines
292 sama5d2_periphck[i].n,292 sama5d2_periphck[i].n,
293 "masterck",293 "masterck",
294 sama5d2_periphck[i].id,294 sama5d2_periphck[i].id,
295 &range);295 &range, INT_MIN);
296 if (IS_ERR(hw))296 if (IS_ERR(hw))
297 goto err_free;297 goto err_free;
298 298
@@ -305,7 +305,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 6 unmodified lines
305 sama5d2_periph32ck[i].n,305 sama5d2_periph32ck[i].n,
306 "h32mxck",306 "h32mxck",
307 sama5d2_periph32ck[i].id,307 sama5d2_periph32ck[i].id,
308 &sama5d2_periph32ck[i].r);308 &sama5d2_periph32ck[i].r,
309 INT_MIN);
309 if (IS_ERR(hw))310 if (IS_ERR(hw))
310 goto err_free;311 goto err_free;
311 312
@@ -322,10 +323,10 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 10 unmodified lines
322 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,323 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
323 &sama5d2_pcr_layout,324 &sama5d2_pcr_layout,
324 sama5d2_gck[i].n,325 sama5d2_gck[i].n,
325 parent_names, 6,326 parent_names, NULL, 6,
326 sama5d2_gck[i].id,327 sama5d2_gck[i].id,
327 sama5d2_gck[i].pll,328 &sama5d2_gck[i].r,
328 &sama5d2_gck[i].r);329 sama5d2_gck[i].chg_pid);
329 if (IS_ERR(hw))330 if (IS_ERR(hw))
330 goto err_free;331 goto err_free;
331 332
drivers/clk/at91/sama5d3.c+5−3
@@ -121,7 +121,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np) · 120 unmodified lines
121 return;121 return;
122 mainxtal_name = of_clk_get_parent_name(np, i);122 mainxtal_name = of_clk_get_parent_name(np, i);
123 123
124 regmap = syscon_node_to_regmap(np);124 regmap = device_node_to_regmap(np);
125 if (IS_ERR(regmap))125 if (IS_ERR(regmap))
126 return;126 return;
127 127
@@ -200,7 +200,8 @@ static void __init sama5d3_pmc_setup(struct device_node *np) · 72 unmodified lines
200 200
201 hw = at91_clk_register_programmable(regmap, name,201 hw = at91_clk_register_programmable(regmap, name,
202 parent_names, 5, i,202 parent_names, 5, i,
203 &at91sam9x5_programmable_layout);203 &at91sam9x5_programmable_layout,
204 NULL);
204 if (IS_ERR(hw))205 if (IS_ERR(hw))
205 goto err_free;206 goto err_free;
206 207
@@ -223,7 +224,8 @@ static void __init sama5d3_pmc_setup(struct device_node *np) · 16 unmodified lines
223 sama5d3_periphck[i].n,224 sama5d3_periphck[i].n,
224 "masterck",225 "masterck",
225 sama5d3_periphck[i].id,226 sama5d3_periphck[i].id,
226 &sama5d3_periphck[i].r);227 &sama5d3_periphck[i].r,
228 INT_MIN);
227 if (IS_ERR(hw))229 if (IS_ERR(hw))
228 goto err_free;230 goto err_free;
229 231
drivers/clk/at91/sama5d4.c+4−3
@@ -223,7 +223,8 @@ static void __init sama5d4_pmc_setup(struct device_node *np) · 222 unmodified lines
223 223
224 hw = at91_clk_register_programmable(regmap, name,224 hw = at91_clk_register_programmable(regmap, name,
225 parent_names, 5, i,225 parent_names, 5, i,
226 &at91sam9x5_programmable_layout);226 &at91sam9x5_programmable_layout,
227 NULL);
227 if (IS_ERR(hw))228 if (IS_ERR(hw))
228 goto err_free;229 goto err_free;
229 230
@@ -246,7 +247,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) · 16 unmodified lines
246 sama5d4_periphck[i].n,247 sama5d4_periphck[i].n,
247 "masterck",248 "masterck",
248 sama5d4_periphck[i].id,249 sama5d4_periphck[i].id,
249 &range);250 &range, INT_MIN);
250 if (IS_ERR(hw))251 if (IS_ERR(hw))
251 goto err_free;252 goto err_free;
252 253
@@ -259,7 +260,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) · 6 unmodified lines
259 sama5d4_periph32ck[i].n,260 sama5d4_periph32ck[i].n,
260 "h32mxck",261 "h32mxck",
261 sama5d4_periph32ck[i].id,262 sama5d4_periph32ck[i].id,
262 &range);263 &range, INT_MIN);
263 if (IS_ERR(hw))264 if (IS_ERR(hw))
264 goto err_free;265 goto err_free;
265 266
drivers/clk/at91/sama7g5.c+1059−0
@@ -0,0 +1,1059 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * SAMA7G5 PMC code.
4 *
5 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
6 *
7 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
8 *
9 */
10#include <linux/clk.h>
11#include <linux/clk-provider.h>
12#include <linux/mfd/syscon.h>
13#include <linux/slab.h>
14
15#include <dt-bindings/clock/at91.h>
16
17#include "pmc.h"
18
19#define SAMA7G5_INIT_TABLE(_table, _count) \
20 do { \
21 u8 _i; \
22 for (_i = 0; _i < (_count); _i++) \
23 (_table)[_i] = _i; \
24 } while (0)
25
26#define SAMA7G5_FILL_TABLE(_to, _from, _count) \
27 do { \
28 u8 _i; \
29 for (_i = 0; _i < (_count); _i++) { \
30 (_to)[_i] = (_from)[_i]; \
31 } \
32 } while (0)
33
34static DEFINE_SPINLOCK(pmc_pll_lock);
35static DEFINE_SPINLOCK(pmc_mckX_lock);
36
37/**
38 * PLL clocks identifiers
39 * @PLL_ID_CPU: CPU PLL identifier
40 * @PLL_ID_SYS: System PLL identifier
41 * @PLL_ID_DDR: DDR PLL identifier
42 * @PLL_ID_IMG: Image subsystem PLL identifier
43 * @PLL_ID_BAUD: Baud PLL identifier
44 * @PLL_ID_AUDIO: Audio PLL identifier
45 * @PLL_ID_ETH: Ethernet PLL identifier
46 */
47enum pll_ids {
48 PLL_ID_CPU,
49 PLL_ID_SYS,
50 PLL_ID_DDR,
51 PLL_ID_IMG,
52 PLL_ID_BAUD,
53 PLL_ID_AUDIO,
54 PLL_ID_ETH,
55 PLL_ID_MAX,
56};
57
58/**
59 * PLL type identifiers
60 * @PLL_TYPE_FRAC: fractional PLL identifier
61 * @PLL_TYPE_DIV: divider PLL identifier
62 */
63enum pll_type {
64 PLL_TYPE_FRAC,
65 PLL_TYPE_DIV,
66};
67
68/* Layout for fractional PLLs. */
69static const struct clk_pll_layout pll_layout_frac = {
70 .mul_mask = GENMASK(31, 24),
71 .frac_mask = GENMASK(21, 0),
72 .mul_shift = 24,
73 .frac_shift = 0,
74};
75
76/* Layout for DIVPMC dividers. */
77static const struct clk_pll_layout pll_layout_divpmc = {
78 .div_mask = GENMASK(7, 0),
79 .endiv_mask = BIT(29),
80 .div_shift = 0,
81 .endiv_shift = 29,
82};
83
84/* Layout for DIVIO dividers. */
85static const struct clk_pll_layout pll_layout_divio = {
86 .div_mask = GENMASK(19, 12),
87 .endiv_mask = BIT(30),
88 .div_shift = 12,
89 .endiv_shift = 30,
90};
91
92/**
93 * PLL clocks description
94 * @n: clock name
95 * @p: clock parent
96 * @l: clock layout
97 * @t: clock type
98 * @f: true if clock is critical and cannot be disabled
99 * @eid: export index in sama7g5->chws[] array
100 */
101static const struct {
102 const char *n;
103 const char *p;
104 const struct clk_pll_layout *l;
105 u8 t;
106 u8 c;
107 u8 eid;
108} sama7g5_plls[][PLL_ID_MAX] = {
109 [PLL_ID_CPU] = {
110 { .n = "cpupll_fracck",
111 .p = "mainck",
112 .l = &pll_layout_frac,
113 .t = PLL_TYPE_FRAC,
114 .c = 1, },
115
116 { .n = "cpupll_divpmcck",
117 .p = "cpupll_fracck",
118 .l = &pll_layout_divpmc,
119 .t = PLL_TYPE_DIV,
120 .c = 1, },
121 },
122
123 [PLL_ID_SYS] = {
124 { .n = "syspll_fracck",
125 .p = "mainck",
126 .l = &pll_layout_frac,
127 .t = PLL_TYPE_FRAC,
128 .c = 1, },
129
130 { .n = "syspll_divpmcck",
131 .p = "syspll_fracck",
132 .l = &pll_layout_divpmc,
133 .t = PLL_TYPE_DIV,
134 .c = 1, },
135 },
136
137 [PLL_ID_DDR] = {
138 { .n = "ddrpll_fracck",
139 .p = "mainck",
140 .l = &pll_layout_frac,
141 .t = PLL_TYPE_FRAC,
142 .c = 1, },
143
144 { .n = "ddrpll_divpmcck",
145 .p = "ddrpll_fracck",
146 .l = &pll_layout_divpmc,
147 .t = PLL_TYPE_DIV,
148 .c = 1, },
149 },
150
151 [PLL_ID_IMG] = {
152 { .n = "imgpll_fracck",
153 .p = "mainck",
154 .l = &pll_layout_frac,
155 .t = PLL_TYPE_FRAC, },
156
157 { .n = "imgpll_divpmcck",
158 .p = "imgpll_fracck",
159 .l = &pll_layout_divpmc,
160 .t = PLL_TYPE_DIV, },
161 },
162
163 [PLL_ID_BAUD] = {
164 { .n = "baudpll_fracck",
165 .p = "mainck",
166 .l = &pll_layout_frac,
167 .t = PLL_TYPE_FRAC, },
168
169 { .n = "baudpll_divpmcck",
170 .p = "baudpll_fracck",
171 .l = &pll_layout_divpmc,
172 .t = PLL_TYPE_DIV, },
173 },
174
175 [PLL_ID_AUDIO] = {
176 { .n = "audiopll_fracck",
177 .p = "main_xtal",
178 .l = &pll_layout_frac,
179 .t = PLL_TYPE_FRAC, },
180
181 { .n = "audiopll_divpmcck",
182 .p = "audiopll_fracck",
183 .l = &pll_layout_divpmc,
184 .t = PLL_TYPE_DIV,
185 .eid = PMC_I2S0_MUX, },
186
187 { .n = "audiopll_diviock",
188 .p = "audiopll_fracck",
189 .l = &pll_layout_divio,
190 .t = PLL_TYPE_DIV,
191 .eid = PMC_I2S1_MUX, },
192 },
193
194 [PLL_ID_ETH] = {
195 { .n = "ethpll_fracck",
196 .p = "main_xtal",
197 .l = &pll_layout_frac,
198 .t = PLL_TYPE_FRAC, },
199
200 { .n = "ethpll_divpmcck",
201 .p = "ethpll_fracck",
202 .l = &pll_layout_divpmc,
203 .t = PLL_TYPE_DIV, },
204 },
205};
206
207/**
208 * Master clock (MCK[1..4]) description
209 * @n: clock name
210 * @ep: extra parents names array
211 * @ep_chg_chg_id: index in parents array that specifies the changeable
212 * parent
213 * @ep_count: extra parents count
214 * @ep_mux_table: mux table for extra parents
215 * @id: clock id
216 * @c: true if clock is critical and cannot be disabled
217 */
218static const struct {
219 const char *n;
220 const char *ep[4];
221 int ep_chg_id;
222 u8 ep_count;
223 u8 ep_mux_table[4];
224 u8 id;
225 u8 c;
226} sama7g5_mckx[] = {
227 { .n = "mck1",
228 .id = 1,
229 .ep = { "syspll_divpmcck", },
230 .ep_mux_table = { 5, },
231 .ep_count = 1,
232 .ep_chg_id = INT_MIN,
233 .c = 1, },
234
235 { .n = "mck2",
236 .id = 2,
237 .ep = { "ddrpll_divpmcck", },
238 .ep_mux_table = { 6, },
239 .ep_count = 1,
240 .ep_chg_id = INT_MIN,
241 .c = 1, },
242
243 { .n = "mck3",
244 .id = 3,
245 .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", },
246 .ep_mux_table = { 5, 6, 7, },
247 .ep_count = 3,
248 .ep_chg_id = 6, },
249
250 { .n = "mck4",
251 .id = 4,
252 .ep = { "syspll_divpmcck", },
253 .ep_mux_table = { 5, },
254 .ep_count = 1,
255 .ep_chg_id = INT_MIN,
256 .c = 1, },
257};
258
259/**
260 * System clock description
261 * @n: clock name
262 * @p: clock parent name
263 * @id: clock id
264 */
265static const struct {
266 const char *n;
267 const char *p;
268 u8 id;
269} sama7g5_systemck[] = {
270 { .n = "pck0", .p = "prog0", .id = 8, },
271 { .n = "pck1", .p = "prog1", .id = 9, },
272 { .n = "pck2", .p = "prog2", .id = 10, },
273 { .n = "pck3", .p = "prog3", .id = 11, },
274 { .n = "pck4", .p = "prog4", .id = 12, },
275 { .n = "pck5", .p = "prog5", .id = 13, },
276 { .n = "pck6", .p = "prog6", .id = 14, },
277 { .n = "pck7", .p = "prog7", .id = 15, },
278};
279
280/* Mux table for programmable clocks. */
281static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, };
282
283/**
284 * Peripheral clock description
285 * @n: clock name
286 * @p: clock parent name
287 * @r: clock range values
288 * @id: clock id
289 * @chgp: index in parent array of the changeable parent
290 */
291static const struct {
292 const char *n;
293 const char *p;
294 struct clk_range r;
295 u8 chgp;
296 u8 id;
297} sama7g5_periphck[] = {
298 { .n = "pioA_clk", .p = "mck0", .id = 11, },
299 { .n = "sfr_clk", .p = "mck1", .id = 19, },
300 { .n = "hsmc_clk", .p = "mck1", .id = 21, },
301 { .n = "xdmac0_clk", .p = "mck1", .id = 22, },
302 { .n = "xdmac1_clk", .p = "mck1", .id = 23, },
303 { .n = "xdmac2_clk", .p = "mck1", .id = 24, },
304 { .n = "acc_clk", .p = "mck1", .id = 25, },
305 { .n = "aes_clk", .p = "mck1", .id = 27, },
306 { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, },
307 { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, },
308 { .n = "cpkcc_clk", .p = "mck0", .id = 32, },
309 { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, .chgp = 1, },
310 { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, .chgp = 1, },
311 { .n = "eic_clk", .p = "mck1", .id = 37, },
312 { .n = "flex0_clk", .p = "mck1", .id = 38, },
313 { .n = "flex1_clk", .p = "mck1", .id = 39, },
314 { .n = "flex2_clk", .p = "mck1", .id = 40, },
315 { .n = "flex3_clk", .p = "mck1", .id = 41, },
316 { .n = "flex4_clk", .p = "mck1", .id = 42, },
317 { .n = "flex5_clk", .p = "mck1", .id = 43, },
318 { .n = "flex6_clk", .p = "mck1", .id = 44, },
319 { .n = "flex7_clk", .p = "mck1", .id = 45, },
320 { .n = "flex8_clk", .p = "mck1", .id = 46, },
321 { .n = "flex9_clk", .p = "mck1", .id = 47, },
322 { .n = "flex10_clk", .p = "mck1", .id = 48, },
323 { .n = "flex11_clk", .p = "mck1", .id = 49, },
324 { .n = "gmac0_clk", .p = "mck1", .id = 51, },
325 { .n = "gmac1_clk", .p = "mck1", .id = 52, },
326 { .n = "icm_clk", .p = "mck1", .id = 55, },
327 { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, .chgp = 1, },
328 { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, },
329 { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, },
330 { .n = "matrix_clk", .p = "mck1", .id = 60, },
331 { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, },
332 { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, },
333 { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, },
334 { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, },
335 { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, },
336 { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, },
337 { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, },
338 { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, },
339 { .n = "pit64b0_clk", .p = "mck1", .id = 70, },
340 { .n = "pit64b1_clk", .p = "mck1", .id = 71, },
341 { .n = "pit64b2_clk", .p = "mck1", .id = 72, },
342 { .n = "pit64b3_clk", .p = "mck1", .id = 73, },
343 { .n = "pit64b4_clk", .p = "mck1", .id = 74, },
344 { .n = "pit64b5_clk", .p = "mck1", .id = 75, },
345 { .n = "pwm_clk", .p = "mck1", .id = 77, },
346 { .n = "qspi0_clk", .p = "mck1", .id = 78, },
347 { .n = "qspi1_clk", .p = "mck1", .id = 79, },
348 { .n = "sdmmc0_clk", .p = "mck1", .id = 80, },
349 { .n = "sdmmc1_clk", .p = "mck1", .id = 81, },
350 { .n = "sdmmc2_clk", .p = "mck1", .id = 82, },
351 { .n = "sha_clk", .p = "mck1", .id = 83, },
352 { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, },
353 { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, },
354 { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, },
355 { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, },
356 { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, },
357 { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, },
358 { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, },
359 { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, },
360 { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, },
361 { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, },
362 { .n = "tcpca_clk", .p = "mck1", .id = 94, },
363 { .n = "tcpcb_clk", .p = "mck1", .id = 95, },
364 { .n = "tdes_clk", .p = "mck1", .id = 96, },
365 { .n = "trng_clk", .p = "mck1", .id = 97, },
366 { .n = "udphsa_clk", .p = "mck1", .id = 104, },
367 { .n = "udphsb_clk", .p = "mck1", .id = 105, },
368 { .n = "uhphs_clk", .p = "mck1", .id = 106, },
369};
370
371/**
372 * Generic clock description
373 * @n: clock name
374 * @pp: PLL parents
375 * @pp_mux_table: PLL parents mux table
376 * @r: clock output range
377 * @pp_chg_id: id in parrent array of changeable PLL parent
378 * @pp_count: PLL parents count
379 * @id: clock id
380 */
381static const struct {
382 const char *n;
383 const char *pp[8];
384 const char pp_mux_table[8];
385 struct clk_range r;
386 int pp_chg_id;
387 u8 pp_count;
388 u8 id;
389} sama7g5_gck[] = {
390 { .n = "adc_gclk",
391 .id = 26,
392 .r = { .max = 100000000, },
393 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", },
394 .pp_mux_table = { 5, 7, 9, },
395 .pp_count = 3,
396 .pp_chg_id = INT_MIN, },
397
398 { .n = "asrc_gclk",
399 .id = 30,
400 .r = { .max = 200000000 },
401 .pp = { "audiopll_divpmcck", },
402 .pp_mux_table = { 9, },
403 .pp_count = 1,
404 .pp_chg_id = 4, },
405
406 { .n = "csi_gclk",
407 .id = 33,
408 .r = { .max = 27000000 },
409 .pp = { "ddrpll_divpmcck", "imgpll_divpmcck", },
410 .pp_mux_table = { 6, 7, },
411 .pp_count = 2,
412 .pp_chg_id = INT_MIN, },
413
414 { .n = "flex0_gclk",
415 .id = 38,
416 .r = { .max = 200000000 },
417 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
418 .pp_mux_table = { 5, 8, },
419 .pp_count = 2,
420 .pp_chg_id = INT_MIN, },
421
422 { .n = "flex1_gclk",
423 .id = 39,
424 .r = { .max = 200000000 },
425 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
426 .pp_mux_table = { 5, 8, },
427 .pp_count = 2,
428 .pp_chg_id = INT_MIN, },
429
430 { .n = "flex2_gclk",
431 .id = 40,
432 .r = { .max = 200000000 },
433 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
434 .pp_mux_table = { 5, 8, },
435 .pp_count = 2,
436 .pp_chg_id = INT_MIN, },
437
438 { .n = "flex3_gclk",
439 .id = 41,
440 .r = { .max = 200000000 },
441 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
442 .pp_mux_table = { 5, 8, },
443 .pp_count = 2,
444 .pp_chg_id = INT_MIN, },
445
446 { .n = "flex4_gclk",
447 .id = 42,
448 .r = { .max = 200000000 },
449 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
450 .pp_mux_table = { 5, 8, },
451 .pp_count = 2,
452 .pp_chg_id = INT_MIN, },
453
454 { .n = "flex5_gclk",
455 .id = 43,
456 .r = { .max = 200000000 },
457 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
458 .pp_mux_table = { 5, 8, },
459 .pp_count = 2,
460 .pp_chg_id = INT_MIN, },
461
462 { .n = "flex6_gclk",
463 .id = 44,
464 .r = { .max = 200000000 },
465 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
466 .pp_mux_table = { 5, 8, },
467 .pp_count = 2,
468 .pp_chg_id = INT_MIN, },
469
470 { .n = "flex7_gclk",
471 .id = 45,
472 .r = { .max = 200000000 },
473 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
474 .pp_mux_table = { 5, 8, },
475 .pp_count = 2,
476 .pp_chg_id = INT_MIN, },
477
478 { .n = "flex8_gclk",
479 .id = 46,
480 .r = { .max = 200000000 },
481 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
482 .pp_mux_table = { 5, 8, },
483 .pp_count = 2,
484 .pp_chg_id = INT_MIN, },
485
486 { .n = "flex9_gclk",
487 .id = 47,
488 .r = { .max = 200000000 },
489 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
490 .pp_mux_table = { 5, 8, },
491 .pp_count = 2,
492 .pp_chg_id = INT_MIN, },
493
494 { .n = "flex10_gclk",
495 .id = 48,
496 .r = { .max = 200000000 },
497 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
498 .pp_mux_table = { 5, 8, },
499 .pp_count = 2,
500 .pp_chg_id = INT_MIN, },
501
502 { .n = "flex11_gclk",
503 .id = 49,
504 .r = { .max = 200000000 },
505 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
506 .pp_mux_table = { 5, 8, },
507 .pp_count = 2,
508 .pp_chg_id = INT_MIN, },
509
510 { .n = "gmac0_gclk",
511 .id = 51,
512 .r = { .max = 125000000 },
513 .pp = { "ethpll_divpmcck", },
514 .pp_mux_table = { 10, },
515 .pp_count = 1,
516 .pp_chg_id = 4, },
517
518 { .n = "gmac1_gclk",
519 .id = 52,
520 .r = { .max = 50000000 },
521 .pp = { "ethpll_divpmcck", },
522 .pp_mux_table = { 10, },
523 .pp_count = 1,
524 .pp_chg_id = INT_MIN, },
525
526 { .n = "gmac0_tsu_gclk",
527 .id = 53,
528 .r = { .max = 300000000 },
529 .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
530 .pp_mux_table = { 9, 10, },
531 .pp_count = 2,
532 .pp_chg_id = INT_MIN, },
533
534 { .n = "gmac1_tsu_gclk",
535 .id = 54,
536 .r = { .max = 300000000 },
537 .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
538 .pp_mux_table = { 9, 10, },
539 .pp_count = 2,
540 .pp_chg_id = INT_MIN, },
541
542 { .n = "i2smcc0_gclk",
543 .id = 57,
544 .r = { .max = 100000000 },
545 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
546 .pp_mux_table = { 5, 9, },
547 .pp_count = 2,
548 .pp_chg_id = 5, },
549
550 { .n = "i2smcc1_gclk",
551 .id = 58,
552 .r = { .max = 100000000 },
553 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
554 .pp_mux_table = { 5, 9, },
555 .pp_count = 2,
556 .pp_chg_id = 5, },
557
558 { .n = "mcan0_gclk",
559 .id = 61,
560 .r = { .max = 200000000 },
561 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
562 .pp_mux_table = { 5, 8, },
563 .pp_count = 2,
564 .pp_chg_id = INT_MIN, },
565
566 { .n = "mcan1_gclk",
567 .id = 62,
568 .r = { .max = 200000000 },
569 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
570 .pp_mux_table = { 5, 8, },
571 .pp_count = 2,
572 .pp_chg_id = INT_MIN, },
573
574 { .n = "mcan2_gclk",
575 .id = 63,
576 .r = { .max = 200000000 },
577 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
578 .pp_mux_table = { 5, 8, },
579 .pp_count = 2,
580 .pp_chg_id = INT_MIN, },
581
582 { .n = "mcan3_gclk",
583 .id = 64,
584 .r = { .max = 200000000 },
585 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
586 .pp_mux_table = { 5, 8, },
587 .pp_count = 2,
588 .pp_chg_id = INT_MIN, },
589
590 { .n = "mcan4_gclk",
591 .id = 65,
592 .r = { .max = 200000000 },
593 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
594 .pp_mux_table = { 5, 8, },
595 .pp_count = 2,
596 .pp_chg_id = INT_MIN, },
597
598 { .n = "mcan5_gclk",
599 .id = 66,
600 .r = { .max = 200000000 },
601 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
602 .pp_mux_table = { 5, 8, },
603 .pp_count = 2,
604 .pp_chg_id = INT_MIN, },
605
606 { .n = "pdmc0_gclk",
607 .id = 68,
608 .r = { .max = 50000000 },
609 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
610 .pp_mux_table = { 5, 8, },
611 .pp_count = 2,
612 .pp_chg_id = INT_MIN, },
613
614 { .n = "pdmc1_gclk",
615 .id = 69,
616 .r = { .max = 50000000, },
617 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
618 .pp_mux_table = { 5, 8, },
619 .pp_count = 2,
620 .pp_chg_id = INT_MIN, },
621
622 { .n = "pit64b0_gclk",
623 .id = 70,
624 .r = { .max = 200000000 },
625 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
626 "audiopll_divpmcck", "ethpll_divpmcck", },
627 .pp_mux_table = { 5, 7, 8, 9, 10, },
628 .pp_count = 5,
629 .pp_chg_id = INT_MIN, },
630
631 { .n = "pit64b1_gclk",
632 .id = 71,
633 .r = { .max = 200000000 },
634 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
635 "audiopll_divpmcck", "ethpll_divpmcck", },
636 .pp_mux_table = { 5, 7, 8, 9, 10, },
637 .pp_count = 5,
638 .pp_chg_id = INT_MIN, },
639
640 { .n = "pit64b2_gclk",
641 .id = 72,
642 .r = { .max = 200000000 },
643 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
644 "audiopll_divpmcck", "ethpll_divpmcck", },
645 .pp_mux_table = { 5, 7, 8, 9, 10, },
646 .pp_count = 5,
647 .pp_chg_id = INT_MIN, },
648
649 { .n = "pit64b3_gclk",
650 .id = 73,
651 .r = { .max = 200000000 },
652 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
653 "audiopll_divpmcck", "ethpll_divpmcck", },
654 .pp_mux_table = { 5, 7, 8, 9, 10, },
655 .pp_count = 5,
656 .pp_chg_id = INT_MIN, },
657
658 { .n = "pit64b4_gclk",
659 .id = 74,
660 .r = { .max = 200000000 },
661 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
662 "audiopll_divpmcck", "ethpll_divpmcck", },
663 .pp_mux_table = { 5, 7, 8, 9, 10, },
664 .pp_count = 5,
665 .pp_chg_id = INT_MIN, },
666
667 { .n = "pit64b5_gclk",
668 .id = 75,
669 .r = { .max = 200000000 },
670 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
671 "audiopll_divpmcck", "ethpll_divpmcck", },
672 .pp_mux_table = { 5, 7, 8, 9, 10, },
673 .pp_count = 5,
674 .pp_chg_id = INT_MIN, },
675
676 { .n = "qspi0_gclk",
677 .id = 78,
678 .r = { .max = 200000000 },
679 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
680 .pp_mux_table = { 5, 8, },
681 .pp_count = 2,
682 .pp_chg_id = INT_MIN, },
683
684 { .n = "qspi1_gclk",
685 .id = 79,
686 .r = { .max = 200000000 },
687 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
688 .pp_mux_table = { 5, 8, },
689 .pp_count = 2,
690 .pp_chg_id = INT_MIN, },
691
692 { .n = "sdmmc0_gclk",
693 .id = 80,
694 .r = { .max = 208000000 },
695 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
696 .pp_mux_table = { 5, 8, },
697 .pp_count = 2,
698 .pp_chg_id = 5, },
699
700 { .n = "sdmmc1_gclk",
701 .id = 81,
702 .r = { .max = 208000000 },
703 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
704 .pp_mux_table = { 5, 8, },
705 .pp_count = 2,
706 .pp_chg_id = 5, },
707
708 { .n = "sdmmc2_gclk",
709 .id = 82,
710 .r = { .max = 208000000 },
711 .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
712 .pp_mux_table = { 5, 8, },
713 .pp_count = 2,
714 .pp_chg_id = 5, },
715
716 { .n = "spdifrx_gclk",
717 .id = 84,
718 .r = { .max = 150000000 },
719 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
720 .pp_mux_table = { 5, 9, },
721 .pp_count = 2,
722 .pp_chg_id = 5, },
723
724 { .n = "spdiftx_gclk",
725 .id = 85,
726 .r = { .max = 25000000 },
727 .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
728 .pp_mux_table = { 5, 9, },
729 .pp_count = 2,
730 .pp_chg_id = 5, },
731
732 { .n = "tcb0_ch0_gclk",
733 .id = 88,
734 .r = { .max = 200000000 },
735 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
736 "audiopll_divpmcck", "ethpll_divpmcck", },
737 .pp_mux_table = { 5, 7, 8, 9, 10, },
738 .pp_count = 5,
739 .pp_chg_id = INT_MIN, },
740
741 { .n = "tcb1_ch0_gclk",
742 .id = 91,
743 .r = { .max = 200000000 },
744 .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
745 "audiopll_divpmcck", "ethpll_divpmcck", },
746 .pp_mux_table = { 5, 7, 8, 9, 10, },
747 .pp_count = 5,
748 .pp_chg_id = INT_MIN, },
749
750 { .n = "tcpca_gclk",
751 .id = 94,
752 .r = { .max = 32768, },
753 .pp_chg_id = INT_MIN, },
754
755 { .n = "tcpcb_gclk",
756 .id = 95,
757 .r = { .max = 32768, },
758 .pp_chg_id = INT_MIN, },
759};
760
761/* PLL output range. */
762static const struct clk_range pll_outputs[] = {
763 { .min = 2343750, .max = 1200000000 },
764};
765
766/* PLL characteristics. */
767static const struct clk_pll_characteristics pll_characteristics = {
768 .input = { .min = 12000000, .max = 50000000 },
769 .num_output = ARRAY_SIZE(pll_outputs),
770 .output = pll_outputs,
771};
772
773/* MCK0 characteristics. */
774static const struct clk_master_characteristics mck0_characteristics = {
775 .output = { .min = 140000000, .max = 200000000 },
776 .divisors = { 1, 2, 4, 3 },
777 .have_div3_pres = 1,
778};
779
780/* MCK0 layout. */
781static const struct clk_master_layout mck0_layout = {
782 .mask = 0x373,
783 .pres_shift = 4,
784 .offset = 0x28,
785};
786
787/* Programmable clock layout. */
788static const struct clk_programmable_layout programmable_layout = {
789 .pres_mask = 0xff,
790 .pres_shift = 8,
791 .css_mask = 0x1f,
792 .have_slck_mck = 0,
793 .is_pres_direct = 1,
794};
795
796/* Peripheral clock layout. */
797static const struct clk_pcr_layout sama7g5_pcr_layout = {
798 .offset = 0x88,
799 .cmd = BIT(31),
800 .gckcss_mask = GENMASK(12, 8),
801 .pid_mask = GENMASK(6, 0),
802};
803
804static void __init sama7g5_pmc_setup(struct device_node *np)
805{
806 const char *td_slck_name, *md_slck_name, *mainxtal_name;
807 struct pmc_data *sama7g5_pmc;
808 const char *parent_names[10];
809 void **alloc_mem = NULL;
810 int alloc_mem_size = 0;
811 struct regmap *regmap;
812 struct clk_hw *hw;
813 bool bypass;
814 int i, j;
815
816 i = of_property_match_string(np, "clock-names", "td_slck");
817 if (i < 0)
818 return;
819
820 td_slck_name = of_clk_get_parent_name(np, i);
821
822 i = of_property_match_string(np, "clock-names", "md_slck");
823 if (i < 0)
824 return;
825
826 md_slck_name = of_clk_get_parent_name(np, i);
827
828 i = of_property_match_string(np, "clock-names", "main_xtal");
829 if (i < 0)
830 return;
831
832 mainxtal_name = of_clk_get_parent_name(np, i);
833
834 regmap = device_node_to_regmap(np);
835 if (IS_ERR(regmap))
836 return;
837
838 sama7g5_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
839 nck(sama7g5_systemck),
840 nck(sama7g5_periphck),
841 nck(sama7g5_gck));
842 if (!sama7g5_pmc)
843 return;
844
845 alloc_mem = kmalloc(sizeof(void *) *
846 (ARRAY_SIZE(sama7g5_mckx) + ARRAY_SIZE(sama7g5_gck)),
847 GFP_KERNEL);
848 if (!alloc_mem)
849 goto err_free;
850
851 hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
852 50000000);
853 if (IS_ERR(hw))
854 goto err_free;
855
856 bypass = of_property_read_bool(np, "atmel,osc-bypass");
857
858 hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
859 bypass);
860 if (IS_ERR(hw))
861 goto err_free;
862
863 parent_names[0] = "main_rc_osc";
864 parent_names[1] = "main_osc";
865 hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
866 if (IS_ERR(hw))
867 goto err_free;
868
869 sama7g5_pmc->chws[PMC_MAIN] = hw;
870
871 for (i = 0; i < PLL_ID_MAX; i++) {
872 for (j = 0; j < 3; j++) {
873 struct clk_hw *parent_hw;
874
875 if (!sama7g5_plls[i][j].n)
876 continue;
877
878 switch (sama7g5_plls[i][j].t) {
879 case PLL_TYPE_FRAC:
880 if (!strcmp(sama7g5_plls[i][j].p, "mainck"))
881 parent_hw = sama7g5_pmc->chws[PMC_MAIN];
882 else
883 parent_hw = __clk_get_hw(of_clk_get_by_name(np,
884 sama7g5_plls[i][j].p));
885
886 hw = sam9x60_clk_register_frac_pll(regmap,
887 &pmc_pll_lock, sama7g5_plls[i][j].n,
888 sama7g5_plls[i][j].p, parent_hw, i,
889 &pll_characteristics,
890 sama7g5_plls[i][j].l,
891 sama7g5_plls[i][j].c);
892 break;
893
894 case PLL_TYPE_DIV:
895 hw = sam9x60_clk_register_div_pll(regmap,
896 &pmc_pll_lock, sama7g5_plls[i][j].n,
897 sama7g5_plls[i][j].p, i,
898 &pll_characteristics,
899 sama7g5_plls[i][j].l,
900 sama7g5_plls[i][j].c);
901 break;
902
903 default:
904 continue;
905 }
906
907 if (IS_ERR(hw))
908 goto err_free;
909
910 if (sama7g5_plls[i][j].eid)
911 sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;
912 }
913 }
914
915 parent_names[0] = md_slck_name;
916 parent_names[1] = "mainck";
917 parent_names[2] = "cpupll_divpmcck";
918 parent_names[3] = "syspll_divpmcck";
919 hw = at91_clk_register_master(regmap, "mck0", 4, parent_names,
920 &mck0_layout, &mck0_characteristics);
921 if (IS_ERR(hw))
922 goto err_free;
923
924 sama7g5_pmc->chws[PMC_MCK] = hw;
925
926 parent_names[0] = md_slck_name;
927 parent_names[1] = td_slck_name;
928 parent_names[2] = "mainck";
929 parent_names[3] = "mck0";
930 for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
931 u8 num_parents = 4 + sama7g5_mckx[i].ep_count;
932 u32 *mux_table;
933
934 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
935 GFP_KERNEL);
936 if (!mux_table)
937 goto err_free;
938
939 SAMA7G5_INIT_TABLE(mux_table, 4);
940 SAMA7G5_FILL_TABLE(&mux_table[4], sama7g5_mckx[i].ep_mux_table,
941 sama7g5_mckx[i].ep_count);
942 SAMA7G5_FILL_TABLE(&parent_names[4], sama7g5_mckx[i].ep,
943 sama7g5_mckx[i].ep_count);
944
945 hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
946 num_parents, parent_names, mux_table,
947 &pmc_mckX_lock, sama7g5_mckx[i].id,
948 sama7g5_mckx[i].c,
949 sama7g5_mckx[i].ep_chg_id);
950 if (IS_ERR(hw))
951 goto err_free;
952
953 alloc_mem[alloc_mem_size++] = mux_table;
954 }
955
956 hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal");
957 if (IS_ERR(hw))
958 goto err_free;
959
960 sama7g5_pmc->chws[PMC_UTMI] = hw;
961
962 parent_names[0] = md_slck_name;
963 parent_names[1] = td_slck_name;
964 parent_names[2] = "mainck";
965 parent_names[3] = "mck0";
966 parent_names[4] = "syspll_divpmcck";
967 parent_names[5] = "ddrpll_divpmcck";
968 parent_names[6] = "imgpll_divpmcck";
969 parent_names[7] = "baudpll_divpmcck";
970 parent_names[8] = "audiopll_divpmcck";
971 parent_names[9] = "ethpll_divpmcck";
972 for (i = 0; i < 8; i++) {
973 char name[6];
974
975 snprintf(name, sizeof(name), "prog%d", i);
976
977 hw = at91_clk_register_programmable(regmap, name, parent_names,
978 10, i,
979 &programmable_layout,
980 sama7g5_prog_mux_table);
981 if (IS_ERR(hw))
982 goto err_free;
983 }
984
985 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
986 hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,
987 sama7g5_systemck[i].p,
988 sama7g5_systemck[i].id);
989 if (IS_ERR(hw))
990 goto err_free;
991
992 sama7g5_pmc->shws[sama7g5_systemck[i].id] = hw;
993 }
994
995 for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) {
996 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
997 &sama7g5_pcr_layout,
998 sama7g5_periphck[i].n,
999 sama7g5_periphck[i].p,
1000 sama7g5_periphck[i].id,
1001 &sama7g5_periphck[i].r,
1002 sama7g5_periphck[i].chgp ? 0 :
1003 INT_MIN);
1004 if (IS_ERR(hw))
1005 goto err_free;
1006
1007 sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;
1008 }
1009
1010 parent_names[0] = md_slck_name;
1011 parent_names[1] = td_slck_name;
1012 parent_names[2] = "mainck";
1013 parent_names[3] = "mck0";
1014 for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
1015 u8 num_parents = 4 + sama7g5_gck[i].pp_count;
1016 u32 *mux_table;
1017
1018 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
1019 GFP_KERNEL);
1020 if (!mux_table)
1021 goto err_free;
1022
1023 SAMA7G5_INIT_TABLE(mux_table, 4);
1024 SAMA7G5_FILL_TABLE(&mux_table[4], sama7g5_gck[i].pp_mux_table,
1025 sama7g5_gck[i].pp_count);
1026 SAMA7G5_FILL_TABLE(&parent_names[4], sama7g5_gck[i].pp,
1027 sama7g5_gck[i].pp_count);
1028
1029 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
1030 &sama7g5_pcr_layout,
1031 sama7g5_gck[i].n,
1032 parent_names, mux_table,
1033 num_parents,
1034 sama7g5_gck[i].id,
1035 &sama7g5_gck[i].r,
1036 sama7g5_gck[i].pp_chg_id);
1037 if (IS_ERR(hw))
1038 goto err_free;
1039
1040 sama7g5_pmc->ghws[sama7g5_gck[i].id] = hw;
1041 alloc_mem[alloc_mem_size++] = mux_table;
1042 }
1043
1044 of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7g5_pmc);
1045
1046 return;
1047
1048err_free:
1049 if (alloc_mem) {
1050 for (i = 0; i < alloc_mem_size; i++)
1051 kfree(alloc_mem[i]);
1052 kfree(alloc_mem);
1053 }
1054
1055 pmc_data_free(sama7g5_pmc);
1056}
1057
1058/* Some clks are used for a clocksource */
1059CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);
drivers/clk/at91/sckc.c+3−2
@@ -471,8 +471,9 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np) · 470 unmodified lines
471 if (!regbase)471 if (!regbase)
472 return;472 return;
473 473
474 slow_rc = clk_hw_register_fixed_rate(NULL, parent_names[0], NULL, 0,474 slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
475 32768);475 NULL, 0, 32768,
476 93750000);
476 if (IS_ERR(slow_rc))477 if (IS_ERR(slow_rc))
477 return;478 return;
478 479
drivers/clk/bcm/clk-bcm2835.c+21−4
@@ -314,6 +314,7 @@ struct bcm2835_cprman { · 313 unmodified lines
314 struct device *dev;314 struct device *dev;
315 void __iomem *regs;315 void __iomem *regs;
316 spinlock_t regs_lock; /* spinlock for all clocks */316 spinlock_t regs_lock; /* spinlock for all clocks */
317 unsigned int soc;
317 318
318 /*319 /*
319 * Real names of cprman clock parents looked up through320 * Real names of cprman clock parents looked up through
@@ -526,6 +527,20 @@ static int bcm2835_pll_is_on(struct clk_hw *hw) · 206 unmodified lines
526 A2W_PLL_CTRL_PRST_DISABLE;527 A2W_PLL_CTRL_PRST_DISABLE;
527}528}
528 529
530static u32 bcm2835_pll_get_prediv_mask(struct bcm2835_cprman *cprman,
531 const struct bcm2835_pll_data *data)
532{
533 /*
534 * On BCM2711 there isn't a pre-divisor available in the PLL feedback
535 * loop. Bits 13:14 of ANA1 (PLLA,PLLB,PLLC,PLLD) have been re-purposed
536 * for to for VCO RANGE bits.
537 */
538 if (cprman->soc & SOC_BCM2711)
539 return 0;
540
541 return data->ana->fb_prediv_mask;
542}
543
529static void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate,544static void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate,
530 unsigned long parent_rate,545 unsigned long parent_rate,
531 u32 *ndiv, u32 *fdiv)546 u32 *ndiv, u32 *fdiv)
@@ -583,7 +598,7 @@ static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw, · 51 unmodified lines
583 ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;598 ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;
584 pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;599 pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;
585 using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &600 using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
586 data->ana->fb_prediv_mask;601 bcm2835_pll_get_prediv_mask(cprman, data);
587 602
588 if (using_prediv) {603 if (using_prediv) {
589 ndiv *= 2;604 ndiv *= 2;
@@ -666,6 +681,7 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, · 76 unmodified lines
666 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);681 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
667 struct bcm2835_cprman *cprman = pll->cprman;682 struct bcm2835_cprman *cprman = pll->cprman;
668 const struct bcm2835_pll_data *data = pll->data;683 const struct bcm2835_pll_data *data = pll->data;
684 u32 prediv_mask = bcm2835_pll_get_prediv_mask(cprman, data);
669 bool was_using_prediv, use_fb_prediv, do_ana_setup_first;685 bool was_using_prediv, use_fb_prediv, do_ana_setup_first;
670 u32 ndiv, fdiv, a2w_ctl;686 u32 ndiv, fdiv, a2w_ctl;
671 u32 ana[4];687 u32 ana[4];
@@ -683,7 +699,7 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, · 11 unmodified lines
683 for (i = 3; i >= 0; i--)699 for (i = 3; i >= 0; i--)
684 ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);700 ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);
685 701
686 was_using_prediv = ana[1] & data->ana->fb_prediv_mask;702 was_using_prediv = ana[1] & prediv_mask;
687 703
688 ana[0] &= ~data->ana->mask0;704 ana[0] &= ~data->ana->mask0;
689 ana[0] |= data->ana->set0;705 ana[0] |= data->ana->set0;
@@ -693,10 +709,10 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, · 3 unmodified lines
693 ana[3] |= data->ana->set3;709 ana[3] |= data->ana->set3;
694 710
695 if (was_using_prediv && !use_fb_prediv) {711 if (was_using_prediv && !use_fb_prediv) {
696 ana[1] &= ~data->ana->fb_prediv_mask;712 ana[1] &= ~prediv_mask;
697 do_ana_setup_first = true;713 do_ana_setup_first = true;
698 } else if (!was_using_prediv && use_fb_prediv) {714 } else if (!was_using_prediv && use_fb_prediv) {
699 ana[1] |= data->ana->fb_prediv_mask;715 ana[1] |= prediv_mask;
700 do_ana_setup_first = false;716 do_ana_setup_first = false;
701 } else {717 } else {
702 do_ana_setup_first = true;718 do_ana_setup_first = true;
@@ -2262,6 +2278,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) · 1559 unmodified lines
2262 platform_set_drvdata(pdev, cprman);2278 platform_set_drvdata(pdev, cprman);
2263 2279
2264 cprman->onecell.num = asize;2280 cprman->onecell.num = asize;
2281 cprman->soc = pdata->soc;
2265 hws = cprman->onecell.hws;2282 hws = cprman->onecell.hws;
2266 2283
2267 for (i = 0; i < asize; i++) {2284 for (i = 0; i < asize; i++) {
drivers/clk/bcm/clk-iproc-asiu.c+2−2
@@ -119,7 +119,7 @@ static long iproc_asiu_clk_round_rate(struct clk_hw *hw, unsigned long rate, · 118 unmodified lines
119 if (rate == *parent_rate)119 if (rate == *parent_rate)
120 return *parent_rate;120 return *parent_rate;
121 121
122 div = DIV_ROUND_UP(*parent_rate, rate);122 div = DIV_ROUND_CLOSEST(*parent_rate, rate);
123 if (div < 2)123 if (div < 2)
124 return *parent_rate;124 return *parent_rate;
125 125
@@ -145,7 +145,7 @@ static int iproc_asiu_clk_set_rate(struct clk_hw *hw, unsigned long rate, · 19 unmodified lines
145 return 0;145 return 0;
146 }146 }
147 147
148 div = DIV_ROUND_UP(parent_rate, rate);148 div = DIV_ROUND_CLOSEST(parent_rate, rate);
149 if (div < 2)149 if (div < 2)
150 return -EINVAL;150 return -EINVAL;
151 151
drivers/clk/clk-qoriq.c+9−1
@@ -244,6 +244,14 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = { · 243 unmodified lines
244 },244 },
245};245};
246 246
247static const struct clockgen_muxinfo ls1021a_cmux = {
248 {
249 { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
250 { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
251 { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
252 }
253};
254
247static const struct clockgen_muxinfo ls1028a_hwa1 = {255static const struct clockgen_muxinfo ls1028a_hwa1 = {
248 {256 {
249 { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },257 { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
@@ -577,7 +585,7 @@ static const struct clockgen_chipinfo chipinfo[] = { · 327 unmodified lines
577 {585 {
578 .compat = "fsl,ls1021a-clockgen",586 .compat = "fsl,ls1021a-clockgen",
579 .cmux_groups = {587 .cmux_groups = {
580 &t1023_cmux588 &ls1021a_cmux
581 },589 },
582 .cmux_to_group = {590 .cmux_to_group = {
583 0, -1591 0, -1
drivers/clk/clk-sparx5.c+295−0
@@ -0,0 +1,295 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Microchip Sparx5 SoC Clock driver.
4 *
5 * Copyright (c) 2019 Microchip Inc.
6 *
7 * Author: Lars Povlsen <lars.povlsen@microchip.com>
8 */
9
10#include <linux/io.h>
11#include <linux/module.h>
12#include <linux/clk-provider.h>
13#include <linux/bitfield.h>
14#include <linux/of.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <dt-bindings/clock/microchip,sparx5.h>
18
19#define PLL_DIV GENMASK(7, 0)
20#define PLL_PRE_DIV GENMASK(10, 8)
21#define PLL_ROT_DIR BIT(11)
22#define PLL_ROT_SEL GENMASK(13, 12)
23#define PLL_ROT_ENA BIT(14)
24#define PLL_CLK_ENA BIT(15)
25
26#define MAX_SEL 4
27#define MAX_PRE BIT(3)
28
29static const u8 sel_rates[MAX_SEL] = { 0, 2*8, 2*4, 2*2 };
30
31static const char *clk_names[N_CLOCKS] = {
32 "core", "ddr", "cpu2", "arm2",
33 "aux1", "aux2", "aux3", "aux4",
34 "synce",
35};
36
37struct s5_hw_clk {
38 struct clk_hw hw;
39 void __iomem *reg;
40};
41
42struct s5_clk_data {
43 void __iomem *base;
44 struct s5_hw_clk s5_hw[N_CLOCKS];
45};
46
47struct s5_pll_conf {
48 unsigned long freq;
49 u8 div;
50 bool rot_ena;
51 u8 rot_sel;
52 u8 rot_dir;
53 u8 pre_div;
54};
55
56#define to_s5_pll(hw) container_of(hw, struct s5_hw_clk, hw)
57
58static unsigned long s5_calc_freq(unsigned long parent_rate,
59 const struct s5_pll_conf *conf)
60{
61 unsigned long rate = parent_rate / conf->div;
62
63 if (conf->rot_ena) {
64 int sign = conf->rot_dir ? -1 : 1;
65 int divt = sel_rates[conf->rot_sel] * (1 + conf->pre_div);
66 int divb = divt + sign;
67
68 rate = mult_frac(rate, divt, divb);
69 rate = roundup(rate, 1000);
70 }
71
72 return rate;
73}
74
75static void s5_search_fractional(unsigned long rate,
76 unsigned long parent_rate,
77 int div,
78 struct s5_pll_conf *conf)
79{
80 struct s5_pll_conf best;
81 ulong cur_offset, best_offset = rate;
82 int d, i, j;
83
84 memset(conf, 0, sizeof(*conf));
85 conf->div = div;
86 conf->rot_ena = 1; /* Fractional rate */
87
88 for (d = 0; best_offset > 0 && d <= 1 ; d++) {
89 conf->rot_dir = !!d;
90 for (i = 0; best_offset > 0 && i < MAX_PRE; i++) {
91 conf->pre_div = i;
92 for (j = 1; best_offset > 0 && j < MAX_SEL; j++) {
93 conf->rot_sel = j;
94 conf->freq = s5_calc_freq(parent_rate, conf);
95 cur_offset = abs(rate - conf->freq);
96 if (cur_offset < best_offset) {
97 best_offset = cur_offset;
98 best = *conf;
99 }
100 }
101 }
102 }
103
104 /* Best match */
105 *conf = best;
106}
107
108static unsigned long s5_calc_params(unsigned long rate,
109 unsigned long parent_rate,
110 struct s5_pll_conf *conf)
111{
112 if (parent_rate % rate) {
113 struct s5_pll_conf alt1, alt2;
114 int div;
115
116 div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate);
117 s5_search_fractional(rate, parent_rate, div, &alt1);
118
119 /* Straight match? */
120 if (alt1.freq == rate) {
121 *conf = alt1;
122 } else {
123 /* Try without rounding divider */
124 div = parent_rate / rate;
125 if (div != alt1.div) {
126 s5_search_fractional(rate, parent_rate, div,
127 &alt2);
128 /* Select the better match */
129 if (abs(rate - alt1.freq) <
130 abs(rate - alt2.freq))
131 *conf = alt1;
132 else
133 *conf = alt2;
134 }
135 }
136 } else {
137 /* Straight fit */
138 memset(conf, 0, sizeof(*conf));
139 conf->div = parent_rate / rate;
140 }
141
142 return conf->freq;
143}
144
145static int s5_pll_enable(struct clk_hw *hw)
146{
147 struct s5_hw_clk *pll = to_s5_pll(hw);
148 u32 val = readl(pll->reg);
149
150 val |= PLL_CLK_ENA;
151 writel(val, pll->reg);
152
153 return 0;
154}
155
156static void s5_pll_disable(struct clk_hw *hw)
157{
158 struct s5_hw_clk *pll = to_s5_pll(hw);
159 u32 val = readl(pll->reg);
160
161 val &= ~PLL_CLK_ENA;
162 writel(val, pll->reg);
163}
164
165static int s5_pll_set_rate(struct clk_hw *hw,
166 unsigned long rate,
167 unsigned long parent_rate)
168{
169 struct s5_hw_clk *pll = to_s5_pll(hw);
170 struct s5_pll_conf conf;
171 unsigned long eff_rate;
172 u32 val;
173
174 eff_rate = s5_calc_params(rate, parent_rate, &conf);
175 if (eff_rate != rate)
176 return -EOPNOTSUPP;
177
178 val = readl(pll->reg) & PLL_CLK_ENA;
179 val |= FIELD_PREP(PLL_DIV, conf.div);
180 if (conf.rot_ena) {
181 val |= PLL_ROT_ENA;
182 val |= FIELD_PREP(PLL_ROT_SEL, conf.rot_sel);
183 val |= FIELD_PREP(PLL_PRE_DIV, conf.pre_div);
184 if (conf.rot_dir)
185 val |= PLL_ROT_DIR;
186 }
187 writel(val, pll->reg);
188
189 return 0;
190}
191
192static unsigned long s5_pll_recalc_rate(struct clk_hw *hw,
193 unsigned long parent_rate)
194{
195 struct s5_hw_clk *pll = to_s5_pll(hw);
196 struct s5_pll_conf conf;
197 u32 val;
198
199 val = readl(pll->reg);
200
201 if (val & PLL_CLK_ENA) {
202 conf.div = FIELD_GET(PLL_DIV, val);
203 conf.pre_div = FIELD_GET(PLL_PRE_DIV, val);
204 conf.rot_ena = FIELD_GET(PLL_ROT_ENA, val);
205 conf.rot_dir = FIELD_GET(PLL_ROT_DIR, val);
206 conf.rot_sel = FIELD_GET(PLL_ROT_SEL, val);
207
208 conf.freq = s5_calc_freq(parent_rate, &conf);
209 } else {
210 conf.freq = 0;
211 }
212
213 return conf.freq;
214}
215
216static long s5_pll_round_rate(struct clk_hw *hw, unsigned long rate,
217 unsigned long *parent_rate)
218{
219 struct s5_pll_conf conf;
220
221 return s5_calc_params(rate, *parent_rate, &conf);
222}
223
224static const struct clk_ops s5_pll_ops = {
225 .enable = s5_pll_enable,
226 .disable = s5_pll_disable,
227 .set_rate = s5_pll_set_rate,
228 .round_rate = s5_pll_round_rate,
229 .recalc_rate = s5_pll_recalc_rate,
230};
231
232static struct clk_hw *s5_clk_hw_get(struct of_phandle_args *clkspec, void *data)
233{
234 struct s5_clk_data *s5_clk = data;
235 unsigned int idx = clkspec->args[0];
236
237 if (idx >= N_CLOCKS) {
238 pr_err("%s: invalid index %u\n", __func__, idx);
239 return ERR_PTR(-EINVAL);
240 }
241
242 return &s5_clk->s5_hw[idx].hw;
243}
244
245static int s5_clk_probe(struct platform_device *pdev)
246{
247 struct device *dev = &pdev->dev;
248 int i, ret;
249 struct s5_clk_data *s5_clk;
250 struct clk_parent_data pdata = { .index = 0 };
251 struct clk_init_data init = {
252 .ops = &s5_pll_ops,
253 .num_parents = 1,
254 .parent_data = &pdata,
255 };
256
257 s5_clk = devm_kzalloc(dev, sizeof(*s5_clk), GFP_KERNEL);
258 if (!s5_clk)
259 return -ENOMEM;
260
261 s5_clk->base = devm_platform_ioremap_resource(pdev, 0);
262 if (IS_ERR(s5_clk->base))
263 return PTR_ERR(s5_clk->base);
264
265 for (i = 0; i < N_CLOCKS; i++) {
266 struct s5_hw_clk *s5_hw = &s5_clk->s5_hw[i];
267
268 init.name = clk_names[i];
269 s5_hw->reg = s5_clk->base + (i * 4);
270 s5_hw->hw.init = &init;
271 ret = devm_clk_hw_register(dev, &s5_hw->hw);
272 if (ret) {
273 dev_err(dev, "failed to register %s clock\n",
274 init.name);
275 return ret;
276 }
277 }
278
279 return devm_of_clk_add_hw_provider(dev, s5_clk_hw_get, s5_clk);
280}
281
282static const struct of_device_id s5_clk_dt_ids[] = {
283 { .compatible = "microchip,sparx5-dpll", },
284 { }
285};
286MODULE_DEVICE_TABLE(of, s5_clk_dt_ids);
287
288static struct platform_driver s5_clk_driver = {
289 .probe = s5_clk_probe,
290 .driver = {
291 .name = "sparx5-clk",
292 .of_match_table = s5_clk_dt_ids,
293 },
294};
295builtin_platform_driver(s5_clk_driver);
drivers/clk/clk-versaclock5.c+38−44
@@ -167,6 +167,12 @@ struct vc5_hw_data { · 166 unmodified lines
167 u32 div_int;167 u32 div_int;
168 u32 div_frc;168 u32 div_frc;
169 unsigned int num;169 unsigned int num;
170};
171
172struct vc5_out_data {
173 struct clk_hw hw;
174 struct vc5_driver_data *vc5;
175 unsigned int num;
170 unsigned int clk_output_cfg0;176 unsigned int clk_output_cfg0;
171 unsigned int clk_output_cfg0_mask;177 unsigned int clk_output_cfg0_mask;
172};178};
@@ -184,7 +190,7 @@ struct vc5_driver_data { · 11 unmodified lines
184 struct clk_hw clk_pfd;190 struct clk_hw clk_pfd;
185 struct vc5_hw_data clk_pll;191 struct vc5_hw_data clk_pll;
186 struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM];192 struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM];
187 struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM];193 struct vc5_out_data clk_out[VC5_MAX_CLK_OUT_NUM];
188};194};
189 195
190/*196/*
@@ -567,7 +573,7 @@ static const struct clk_ops vc5_fod_ops = { · 376 unmodified lines
567 573
568static int vc5_clk_out_prepare(struct clk_hw *hw)574static int vc5_clk_out_prepare(struct clk_hw *hw)
569{575{
570 struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);576 struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
571 struct vc5_driver_data *vc5 = hwdata->vc5;577 struct vc5_driver_data *vc5 = hwdata->vc5;
572 const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM |578 const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM |
573 VC5_OUT_DIV_CONTROL_SEL_EXT |579 VC5_OUT_DIV_CONTROL_SEL_EXT |
@@ -609,7 +615,7 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) · 35 unmodified lines
609 615
610static void vc5_clk_out_unprepare(struct clk_hw *hw)616static void vc5_clk_out_unprepare(struct clk_hw *hw)
611{617{
612 struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);618 struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
613 struct vc5_driver_data *vc5 = hwdata->vc5;619 struct vc5_driver_data *vc5 = hwdata->vc5;
614 620
615 /* Disable the clock buffer */621 /* Disable the clock buffer */
@@ -619,7 +625,7 @@ static void vc5_clk_out_unprepare(struct clk_hw *hw) · 3 unmodified lines
619 625
620static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw)626static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw)
621{627{
622 struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);628 struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
623 struct vc5_driver_data *vc5 = hwdata->vc5;629 struct vc5_driver_data *vc5 = hwdata->vc5;
624 const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM |630 const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM |
625 VC5_OUT_DIV_CONTROL_SEL_EXT |631 VC5_OUT_DIV_CONTROL_SEL_EXT |
@@ -649,7 +655,7 @@ static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw) · 23 unmodified lines
649 655
650static int vc5_clk_out_set_parent(struct clk_hw *hw, u8 index)656static int vc5_clk_out_set_parent(struct clk_hw *hw, u8 index)
651{657{
652 struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);658 struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw);
653 struct vc5_driver_data *vc5 = hwdata->vc5;659 struct vc5_driver_data *vc5 = hwdata->vc5;
654 const u8 mask = VC5_OUT_DIV_CONTROL_RESET |660 const u8 mask = VC5_OUT_DIV_CONTROL_RESET |
655 VC5_OUT_DIV_CONTROL_SELB_NORM |661 VC5_OUT_DIV_CONTROL_SELB_NORM |
@@ -704,7 +710,7 @@ static int vc5_map_index_to_output(const enum vc5_model model, · 48 unmodified lines
704}710}
705 711
706static int vc5_update_mode(struct device_node *np_output,712static int vc5_update_mode(struct device_node *np_output,
707 struct vc5_hw_data *clk_out)713 struct vc5_out_data *clk_out)
708{714{
709 u32 value;715 u32 value;
710 716
@@ -729,7 +735,7 @@ static int vc5_update_mode(struct device_node *np_output, · 18 unmodified lines
729}735}
730 736
731static int vc5_update_power(struct device_node *np_output,737static int vc5_update_power(struct device_node *np_output,
732 struct vc5_hw_data *clk_out)738 struct vc5_out_data *clk_out)
733{739{
734 u32 value;740 u32 value;
735 741
@@ -754,7 +760,7 @@ static int vc5_update_power(struct device_node *np_output, · 18 unmodified lines
754}760}
755 761
756static int vc5_update_slew(struct device_node *np_output,762static int vc5_update_slew(struct device_node *np_output,
757 struct vc5_hw_data *clk_out)763 struct vc5_out_data *clk_out)
758{764{
759 u32 value;765 u32 value;
760 766
@@ -782,17 +788,20 @@ static int vc5_update_slew(struct device_node *np_output, · 21 unmodified lines
782}788}
783 789
784static int vc5_get_output_config(struct i2c_client *client,790static int vc5_get_output_config(struct i2c_client *client,
785 struct vc5_hw_data *clk_out)791 struct vc5_out_data *clk_out)
786{792{
787 struct device_node *np_output;793 struct device_node *np_output;
788 char *child_name;794 char *child_name;
789 int ret = 0;795 int ret = 0;
790 796
791 child_name = kasprintf(GFP_KERNEL, "OUT%d", clk_out->num + 1);797 child_name = kasprintf(GFP_KERNEL, "OUT%d", clk_out->num + 1);
798 if (!child_name)
799 return -ENOMEM;
800
792 np_output = of_get_child_by_name(client->dev.of_node, child_name);801 np_output = of_get_child_by_name(client->dev.of_node, child_name);
793 kfree(child_name);802 kfree(child_name);
794 if (!np_output)803 if (!np_output)
795 goto output_done;804 return 0;
796 805
797 ret = vc5_update_mode(np_output, clk_out);806 ret = vc5_update_mode(np_output, clk_out);
798 if (ret)807 if (ret)
@@ -813,7 +822,6 @@ output_error: · 14 unmodified lines
813 822
814 of_node_put(np_output);823 of_node_put(np_output);
815 824
816output_done:
817 return ret;825 return ret;
818}826}
819 827
@@ -828,7 +836,7 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 8 unmodified lines
828 int ret;836 int ret;
829 837
830 vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL);838 vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL);
831 if (vc5 == NULL)839 if (!vc5)
832 return -ENOMEM;840 return -ENOMEM;
833 841
834 i2c_set_clientdata(client, vc5);842 i2c_set_clientdata(client, vc5);
@@ -882,11 +890,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 47 unmodified lines
882 init.parent_names = parent_names;890 init.parent_names = parent_names;
883 vc5->clk_mux.init = &init;891 vc5->clk_mux.init = &init;
884 ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux);892 ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux);
893 if (ret)
894 goto err_clk_register;
885 kfree(init.name); /* clock framework made a copy of the name */895 kfree(init.name); /* clock framework made a copy of the name */
886 if (ret) {
887 dev_err(&client->dev, "unable to register %s\n", init.name);
888 goto err_clk;
889 }
890 896
891 if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) {897 if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) {
892 /* Register frequency doubler */898 /* Register frequency doubler */
@@ -900,12 +906,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 7 unmodified lines
900 init.num_parents = 1;906 init.num_parents = 1;
901 vc5->clk_mul.init = &init;907 vc5->clk_mul.init = &init;
902 ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul);908 ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul);
909 if (ret)
910 goto err_clk_register;
903 kfree(init.name); /* clock framework made a copy of the name */911 kfree(init.name); /* clock framework made a copy of the name */
904 if (ret) {
905 dev_err(&client->dev, "unable to register %s\n",
906 init.name);
907 goto err_clk;
908 }
909 }912 }
910 913
911 /* Register PFD */914 /* Register PFD */
@@ -921,11 +924,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 9 unmodified lines
921 init.num_parents = 1;924 init.num_parents = 1;
922 vc5->clk_pfd.init = &init;925 vc5->clk_pfd.init = &init;
923 ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd);926 ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd);
927 if (ret)
928 goto err_clk_register;
924 kfree(init.name); /* clock framework made a copy of the name */929 kfree(init.name); /* clock framework made a copy of the name */
925 if (ret) {
926 dev_err(&client->dev, "unable to register %s\n", init.name);
927 goto err_clk;
928 }
929 930
930 /* Register PLL */931 /* Register PLL */
931 memset(&init, 0, sizeof(init));932 memset(&init, 0, sizeof(init));
@@ -939,11 +940,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 7 unmodified lines
939 vc5->clk_pll.vc5 = vc5;940 vc5->clk_pll.vc5 = vc5;
940 vc5->clk_pll.hw.init = &init;941 vc5->clk_pll.hw.init = &init;
941 ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw);942 ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw);
943 if (ret)
944 goto err_clk_register;
942 kfree(init.name); /* clock framework made a copy of the name */945 kfree(init.name); /* clock framework made a copy of the name */
943 if (ret) {
944 dev_err(&client->dev, "unable to register %s\n", init.name);
945 goto err_clk;
946 }
947 946
948 /* Register FODs */947 /* Register FODs */
949 for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {948 for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {
@@ -960,12 +959,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 10 unmodified lines
960 vc5->clk_fod[n].vc5 = vc5;959 vc5->clk_fod[n].vc5 = vc5;
961 vc5->clk_fod[n].hw.init = &init;960 vc5->clk_fod[n].hw.init = &init;
962 ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw);961 ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw);
962 if (ret)
963 goto err_clk_register;
963 kfree(init.name); /* clock framework made a copy of the name */964 kfree(init.name); /* clock framework made a copy of the name */
964 if (ret) {
965 dev_err(&client->dev, "unable to register %s\n",
966 init.name);
967 goto err_clk;
968 }
969 }965 }
970 966
971 /* Register MUX-connected OUT0_I2C_SELB output */967 /* Register MUX-connected OUT0_I2C_SELB output */
@@ -981,11 +977,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 9 unmodified lines
981 vc5->clk_out[0].vc5 = vc5;977 vc5->clk_out[0].vc5 = vc5;
982 vc5->clk_out[0].hw.init = &init;978 vc5->clk_out[0].hw.init = &init;
983 ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw);979 ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw);
984 kfree(init.name); /* clock framework made a copy of the name */980 if (ret)
985 if (ret) {981 goto err_clk_register;
986 dev_err(&client->dev, "unable to register %s\n", init.name);982 kfree(init.name); /* clock framework made a copy of the name */
987 goto err_clk;
988 }
989 983
990 /* Register FOD-connected OUTx outputs */984 /* Register FOD-connected OUTx outputs */
991 for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {985 for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {
@@ -1008,12 +1002,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 16 unmodified lines
1008 vc5->clk_out[n].vc5 = vc5;1002 vc5->clk_out[n].vc5 = vc5;
1009 vc5->clk_out[n].hw.init = &init;1003 vc5->clk_out[n].hw.init = &init;
1010 ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw);1004 ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw);
1005 if (ret)
1006 goto err_clk_register;
1011 kfree(init.name); /* clock framework made a copy of the name */1007 kfree(init.name); /* clock framework made a copy of the name */
1012 if (ret) {
1013 dev_err(&client->dev, "unable to register %s\n",
1014 init.name);
1015 goto err_clk;
1016 }
1017 1008
1018 /* Fetch Clock Output configuration from DT (if specified) */1009 /* Fetch Clock Output configuration from DT (if specified) */
1019 ret = vc5_get_output_config(client, &vc5->clk_out[n]);1010 ret = vc5_get_output_config(client, &vc5->clk_out[n]);
@@ -1029,6 +1020,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) · 9 unmodified lines
1029 1020
1030 return 0;1021 return 0;
1031 1022
1023err_clk_register:
1024 dev_err(&client->dev, "unable to register %s\n", init.name);
1025 kfree(init.name); /* clock framework made a copy of the name */
1032err_clk:1026err_clk:
1033 if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)1027 if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
1034 clk_unregister_fixed_rate(vc5->pin_xin);1028 clk_unregister_fixed_rate(vc5->pin_xin);
drivers/clk/clk.c+32−6
@@ -500,12 +500,6 @@ static unsigned long clk_core_get_accuracy_no_lock(struct clk_core *core) · 499 unmodified lines
500 return core->accuracy;500 return core->accuracy;
501}501}
502 502
503unsigned long __clk_get_flags(struct clk *clk)
504{
505 return !clk ? 0 : clk->core->flags;
506}
507EXPORT_SYMBOL_GPL(__clk_get_flags);
508
509unsigned long clk_hw_get_flags(const struct clk_hw *hw)503unsigned long clk_hw_get_flags(const struct clk_hw *hw)
510{504{
511 return hw->core->flags;505 return hw->core->flags;
@@ -3054,6 +3048,31 @@ static int clk_rate_set(void *data, u64 val) · 2542 unmodified lines
3054}3048}
3055 3049
3056#define clk_rate_mode 06443050#define clk_rate_mode 0644
3051
3052static int clk_prepare_enable_set(void *data, u64 val)
3053{
3054 struct clk_core *core = data;
3055 int ret = 0;
3056
3057 if (val)
3058 ret = clk_prepare_enable(core->hw->clk);
3059 else
3060 clk_disable_unprepare(core->hw->clk);
3061
3062 return ret;
3063}
3064
3065static int clk_prepare_enable_get(void *data, u64 *val)
3066{
3067 struct clk_core *core = data;
3068
3069 *val = core->enable_count && core->prepare_count;
3070 return 0;
3071}
3072
3073DEFINE_DEBUGFS_ATTRIBUTE(clk_prepare_enable_fops, clk_prepare_enable_get,
3074 clk_prepare_enable_set, "%llu\n");
3075
3057#else3076#else
3058#define clk_rate_set NULL3077#define clk_rate_set NULL
3059#define clk_rate_mode 04443078#define clk_rate_mode 0444
@@ -3231,6 +3250,10 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) · 171 unmodified lines
3231 debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count);3250 debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count);
3232 debugfs_create_file("clk_duty_cycle", 0444, root, core,3251 debugfs_create_file("clk_duty_cycle", 0444, root, core,
3233 &clk_duty_cycle_fops);3252 &clk_duty_cycle_fops);
3253#ifdef CLOCK_ALLOW_WRITE_DEBUGFS
3254 debugfs_create_file("clk_prepare_enable", 0644, root, core,
3255 &clk_prepare_enable_fops);
3256#endif
3234 3257
3235 if (core->num_parents > 0)3258 if (core->num_parents > 0)
3236 debugfs_create_file("clk_parent", 0444, root, core,3259 debugfs_create_file("clk_parent", 0444, root, core,
@@ -4135,6 +4158,7 @@ static int devm_clk_hw_match(struct device *dev, void *res, void *data) · 898 unmodified lines
4135 4158
4136/**4159/**
4137 * devm_clk_unregister - resource managed clk_unregister()4160 * devm_clk_unregister - resource managed clk_unregister()
4161 * @dev: device that is unregistering the clock data
4138 * @clk: clock to unregister4162 * @clk: clock to unregister
4139 *4163 *
4140 * Deallocate a clock allocated with devm_clk_register(). Normally4164 * Deallocate a clock allocated with devm_clk_register(). Normally
@@ -4324,6 +4348,8 @@ static void clk_core_reparent_orphans(void) · 183 unmodified lines
4324 * @node: Pointer to device tree node of clock provider4348 * @node: Pointer to device tree node of clock provider
4325 * @get: Get clock callback. Returns NULL or a struct clk for the4349 * @get: Get clock callback. Returns NULL or a struct clk for the
4326 * given clock specifier4350 * given clock specifier
4351 * @get_hw: Get clk_hw callback. Returns NULL, ERR_PTR or a
4352 * struct clk_hw for the given clock specifier
4327 * @data: context pointer to be passed into @get callback4353 * @data: context pointer to be passed into @get callback
4328 */4354 */
4329struct of_clk_provider {4355struct of_clk_provider {
drivers/clk/davinci/pll.c+1−1
@@ -651,7 +651,7 @@ static int davinci_pll_sysclk_rate_change(struct notifier_block *nb, · 650 unmodified lines
651 pllcmd = readl(pll->base + PLLCMD);651 pllcmd = readl(pll->base + PLLCMD);
652 pllcmd |= PLLCMD_GOSET;652 pllcmd |= PLLCMD_GOSET;
653 writel(pllcmd, pll->base + PLLCMD);653 writel(pllcmd, pll->base + PLLCMD);
654 /* fallthrough */654 fallthrough;
655 case PRE_RATE_CHANGE:655 case PRE_RATE_CHANGE:
656 /* Wait until for outstanding changes to take effect */656 /* Wait until for outstanding changes to take effect */
657 do {657 do {
drivers/clk/imx/clk-pllv3.c+2−2
@@ -433,7 +433,7 @@ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, · 432 unmodified lines
433 break;433 break;
434 case IMX_PLLV3_USB_VF610:434 case IMX_PLLV3_USB_VF610:
435 pll->div_shift = 1;435 pll->div_shift = 1;
436 /* fall through */436 fallthrough;
437 case IMX_PLLV3_USB:437 case IMX_PLLV3_USB:
438 ops = &clk_pllv3_ops;438 ops = &clk_pllv3_ops;
439 pll->powerup_set = true;439 pll->powerup_set = true;
@@ -441,7 +441,7 @@ struct clk_hw *imx_clk_hw_pllv3(enum imx_pllv3_type type, const char *name, · 1 unmodified line
441 case IMX_PLLV3_AV_IMX7:441 case IMX_PLLV3_AV_IMX7:
442 pll->num_offset = PLL_IMX7_NUM_OFFSET;442 pll->num_offset = PLL_IMX7_NUM_OFFSET;
443 pll->denom_offset = PLL_IMX7_DENOM_OFFSET;443 pll->denom_offset = PLL_IMX7_DENOM_OFFSET;
444 /* fall through */444 fallthrough;
445 case IMX_PLLV3_AV:445 case IMX_PLLV3_AV:
446 ops = &clk_pllv3_av_ops;446 ops = &clk_pllv3_av_ops;
447 break;447 break;
drivers/clk/ingenic/jz4780-cgu.c+91−74
@@ -4,6 +4,7 @@ · 3 unmodified lines
4 *4 *
5 * Copyright (c) 2013-2015 Imagination Technologies5 * Copyright (c) 2013-2015 Imagination Technologies
6 * Author: Paul Burton <paul.burton@mips.com>6 * Author: Paul Burton <paul.burton@mips.com>
7 * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
7 */8 */
8 9
9#include <linux/clk-provider.h>10#include <linux/clk-provider.h>
@@ -19,49 +20,50 @@ · 9 unmodified lines
19 20
20/* CGU register offsets */21/* CGU register offsets */
21#define CGU_REG_CLOCKCONTROL 0x0022#define CGU_REG_CLOCKCONTROL 0x00
22#define CGU_REG_LCR 0x0423#define CGU_REG_LCR 0x04
23#define CGU_REG_APLL 0x1024#define CGU_REG_APLL 0x10
24#define CGU_REG_MPLL 0x1425#define CGU_REG_MPLL 0x14
25#define CGU_REG_EPLL 0x1826#define CGU_REG_EPLL 0x18
26#define CGU_REG_VPLL 0x1c27#define CGU_REG_VPLL 0x1c
27#define CGU_REG_CLKGR0 0x2028#define CGU_REG_CLKGR0 0x20
28#define CGU_REG_OPCR 0x2429#define CGU_REG_OPCR 0x24
29#define CGU_REG_CLKGR1 0x2830#define CGU_REG_CLKGR1 0x28
30#define CGU_REG_DDRCDR 0x2c31#define CGU_REG_DDRCDR 0x2c
31#define CGU_REG_VPUCDR 0x3032#define CGU_REG_VPUCDR 0x30
32#define CGU_REG_USBPCR 0x3c33#define CGU_REG_USBPCR 0x3c
33#define CGU_REG_USBRDT 0x4034#define CGU_REG_USBRDT 0x40
34#define CGU_REG_USBVBFIL 0x4435#define CGU_REG_USBVBFIL 0x44
35#define CGU_REG_USBPCR1 0x4836#define CGU_REG_USBPCR1 0x48
36#define CGU_REG_LP0CDR 0x5437#define CGU_REG_LP0CDR 0x54
37#define CGU_REG_I2SCDR 0x6038#define CGU_REG_I2SCDR 0x60
38#define CGU_REG_LP1CDR 0x6439#define CGU_REG_LP1CDR 0x64
39#define CGU_REG_MSC0CDR 0x6840#define CGU_REG_MSC0CDR 0x68
40#define CGU_REG_UHCCDR 0x6c41#define CGU_REG_UHCCDR 0x6c
41#define CGU_REG_SSICDR 0x7442#define CGU_REG_SSICDR 0x74
42#define CGU_REG_CIMCDR 0x7c43#define CGU_REG_CIMCDR 0x7c
43#define CGU_REG_PCMCDR 0x8444#define CGU_REG_PCMCDR 0x84
44#define CGU_REG_GPUCDR 0x8845#define CGU_REG_GPUCDR 0x88
45#define CGU_REG_HDMICDR 0x8c46#define CGU_REG_HDMICDR 0x8c
46#define CGU_REG_MSC1CDR 0xa447#define CGU_REG_MSC1CDR 0xa4
47#define CGU_REG_MSC2CDR 0xa848#define CGU_REG_MSC2CDR 0xa8
48#define CGU_REG_BCHCDR 0xac49#define CGU_REG_BCHCDR 0xac
49#define CGU_REG_CLOCKSTATUS 0xd450#define CGU_REG_CLOCKSTATUS 0xd4
50 51
51/* bits within the OPCR register */52/* bits within the OPCR register */
52#define OPCR_SPENDN0 BIT(7)53#define OPCR_SPENDN0 BIT(7)
53#define OPCR_SPENDN1 BIT(6)54#define OPCR_SPENDN1 BIT(6)
54 55
55/* bits within the USBPCR register */56/* bits within the USBPCR register */
56#define USBPCR_USB_MODE BIT(31)57#define USBPCR_USB_MODE BIT(31)
57#define USBPCR_IDPULLUP_MASK (0x3 << 28)58#define USBPCR_IDPULLUP_MASK (0x3 << 28)
58#define USBPCR_COMMONONN BIT(25)59#define USBPCR_COMMONONN BIT(25)
59#define USBPCR_VBUSVLDEXT BIT(24)60#define USBPCR_VBUSVLDEXT BIT(24)
60#define USBPCR_VBUSVLDEXTSEL BIT(23)61#define USBPCR_VBUSVLDEXTSEL BIT(23)
61#define USBPCR_POR BIT(22)62#define USBPCR_POR BIT(22)
62#define USBPCR_OTG_DISABLE BIT(20)63#define USBPCR_SIDDQ BIT(21)
64#define USBPCR_OTG_DISABLE BIT(20)
63#define USBPCR_COMPDISTUNE_MASK (0x7 << 17)65#define USBPCR_COMPDISTUNE_MASK (0x7 << 17)
64#define USBPCR_OTGTUNE_MASK (0x7 << 14)66#define USBPCR_OTGTUNE_MASK (0x7 << 14)
65#define USBPCR_SQRXTUNE_MASK (0x7 << 11)67#define USBPCR_SQRXTUNE_MASK (0x7 << 11)
66#define USBPCR_TXFSLSTUNE_MASK (0xf << 7)68#define USBPCR_TXFSLSTUNE_MASK (0xf << 7)
67#define USBPCR_TXPREEMPHTUNE BIT(6)69#define USBPCR_TXPREEMPHTUNE BIT(6)
@@ -78,13 +80,13 @@ · 10 unmodified lines
78#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)80#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
79#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)81#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
80#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)82#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
81#define USBPCR1_USB_SEL BIT(28)83#define USBPCR1_USB_SEL BIT(28)
82#define USBPCR1_WORD_IF0 BIT(19)84#define USBPCR1_WORD_IF0 BIT(19)
83#define USBPCR1_WORD_IF1 BIT(18)85#define USBPCR1_WORD_IF1 BIT(18)
84 86
85/* bits within the USBRDT register */87/* bits within the USBRDT register */
86#define USBRDT_VBFIL_LD_EN BIT(25)88#define USBRDT_VBFIL_LD_EN BIT(25)
87#define USBRDT_USBRDT_MASK 0x7fffff89#define USBRDT_USBRDT_MASK 0x7fffff
88 90
89/* bits within the USBVBFIL register */91/* bits within the USBVBFIL register */
90#define USBVBFIL_IDDIGFIL_SHIFT 1692#define USBVBFIL_IDDIGFIL_SHIFT 16
@@ -92,40 +94,14 @@ · 1 unmodified line
92#define USBVBFIL_USBVBFIL_MASK (0xffff)94#define USBVBFIL_USBVBFIL_MASK (0xffff)
93 95
94/* bits within the LCR register */96/* bits within the LCR register */
95#define LCR_PD_SCPU BIT(31)97#define LCR_PD_SCPU BIT(31)
96#define LCR_SCPUS BIT(27)98#define LCR_SCPUS BIT(27)
97 99
98/* bits within the CLKGR1 register */100/* bits within the CLKGR1 register */
99#define CLKGR1_CORE1 BIT(15)101#define CLKGR1_CORE1 BIT(15)
100 102
101static struct ingenic_cgu *cgu;103static struct ingenic_cgu *cgu;
102 104
103static u8 jz4780_otg_phy_get_parent(struct clk_hw *hw)
104{
105 /* we only use CLKCORE, revisit if that ever changes */
106 return 0;
107}
108
109static int jz4780_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
110{
111 unsigned long flags;
112 u32 usbpcr1;
113
114 if (idx > 0)
115 return -EINVAL;
116
117 spin_lock_irqsave(&cgu->lock, flags);
118
119 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
120 usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
121 /* we only use CLKCORE */
122 usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
123 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
124
125 spin_unlock_irqrestore(&cgu->lock, flags);
126 return 0;
127}
128
129static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,105static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,
130 unsigned long parent_rate)106 unsigned long parent_rate)
131{107{
@@ -149,7 +125,6 @@ static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw, · 17 unmodified lines
149 return 19200000;125 return 19200000;
150 }126 }
151 127
152 BUG();
153 return parent_rate;128 return parent_rate;
154}129}
155 130
@@ -206,13 +181,43 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate, · 50 unmodified lines
206 return 0;181 return 0;
207}182}
208 183
209static const struct clk_ops jz4780_otg_phy_ops = {184static int jz4780_otg_phy_enable(struct clk_hw *hw)
210 .get_parent = jz4780_otg_phy_get_parent,185{
211 .set_parent = jz4780_otg_phy_set_parent,186 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
187 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
188
189 writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
190 writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
191 return 0;
192}
212 193
194static void jz4780_otg_phy_disable(struct clk_hw *hw)
195{
196 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
197 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
198
199 writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
200 writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
201}
202
203static int jz4780_otg_phy_is_enabled(struct clk_hw *hw)
204{
205 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
206 void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
207
208 return (readl(reg_opcr) & OPCR_SPENDN0) &&
209 !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
210 !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
211}
212
213static const struct clk_ops jz4780_otg_phy_ops = {
213 .recalc_rate = jz4780_otg_phy_recalc_rate,214 .recalc_rate = jz4780_otg_phy_recalc_rate,
214 .round_rate = jz4780_otg_phy_round_rate,215 .round_rate = jz4780_otg_phy_round_rate,
215 .set_rate = jz4780_otg_phy_set_rate,216 .set_rate = jz4780_otg_phy_set_rate,
217
218 .enable = jz4780_otg_phy_enable,
219 .disable = jz4780_otg_phy_disable,
220 .is_enabled = jz4780_otg_phy_is_enabled,
216};221};
217 222
218static int jz4780_core1_enable(struct clk_hw *hw)223static int jz4780_core1_enable(struct clk_hw *hw)
@@ -516,6 +521,18 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { · 297 unmodified lines
516 .gate = { CGU_REG_CLKGR0, 1 },521 .gate = { CGU_REG_CLKGR0, 1 },
517 },522 },
518 523
524 [JZ4780_CLK_EXCLK_DIV512] = {
525 "exclk_div512", CGU_CLK_FIXDIV,
526 .parents = { JZ4780_CLK_EXCLK },
527 .fixdiv = { 512 },
528 },
529
530 [JZ4780_CLK_RTC] = {
531 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
532 .parents = { JZ4780_CLK_EXCLK_DIV512, JZ4780_CLK_RTCLK },
533 .mux = { CGU_REG_OPCR, 2, 1},
534 },
535
519 /* Gate-only clocks */536 /* Gate-only clocks */
520 537
521 [JZ4780_CLK_NEMC] = {538 [JZ4780_CLK_NEMC] = {
drivers/clk/ingenic/x1000-cgu.c+96−1
@@ -48,8 +48,87 @@ · 47 unmodified lines
48#define USBPCR_SIDDQ BIT(21)48#define USBPCR_SIDDQ BIT(21)
49#define USBPCR_OTG_DISABLE BIT(20)49#define USBPCR_OTG_DISABLE BIT(20)
50 50
51/* bits within the USBPCR1 register */
52#define USBPCR1_REFCLKSEL_SHIFT 26
53#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)
54#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)
55#define USBPCR1_REFCLKDIV_SHIFT 24
56#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)
57#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
58#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
59#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
60
51static struct ingenic_cgu *cgu;61static struct ingenic_cgu *cgu;
52 62
63static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
64 unsigned long parent_rate)
65{
66 u32 usbpcr1;
67 unsigned refclk_div;
68
69 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
70 refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
71
72 switch (refclk_div) {
73 case USBPCR1_REFCLKDIV_12:
74 return 12000000;
75
76 case USBPCR1_REFCLKDIV_24:
77 return 24000000;
78
79 case USBPCR1_REFCLKDIV_48:
80 return 48000000;
81 }
82
83 return parent_rate;
84}
85
86static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
87 unsigned long *parent_rate)
88{
89 if (req_rate < 18000000)
90 return 12000000;
91
92 if (req_rate < 36000000)
93 return 24000000;
94
95 return 48000000;
96}
97
98static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
99 unsigned long parent_rate)
100{
101 unsigned long flags;
102 u32 usbpcr1, div_bits;
103
104 switch (req_rate) {
105 case 12000000:
106 div_bits = USBPCR1_REFCLKDIV_12;
107 break;
108
109 case 24000000:
110 div_bits = USBPCR1_REFCLKDIV_24;
111 break;
112
113 case 48000000:
114 div_bits = USBPCR1_REFCLKDIV_48;
115 break;
116
117 default:
118 return -EINVAL;
119 }
120
121 spin_lock_irqsave(&cgu->lock, flags);
122
123 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
124 usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
125 usbpcr1 |= div_bits;
126 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
127
128 spin_unlock_irqrestore(&cgu->lock, flags);
129 return 0;
130}
131
53static int x1000_usb_phy_enable(struct clk_hw *hw)132static int x1000_usb_phy_enable(struct clk_hw *hw)
54{133{
55 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;134 void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
@@ -80,6 +159,10 @@ static int x1000_usb_phy_is_enabled(struct clk_hw *hw) · 24 unmodified lines
80}159}
81 160
82static const struct clk_ops x1000_otg_phy_ops = {161static const struct clk_ops x1000_otg_phy_ops = {
162 .recalc_rate = x1000_otg_phy_recalc_rate,
163 .round_rate = x1000_otg_phy_round_rate,
164 .set_rate = x1000_otg_phy_set_rate,
165
83 .enable = x1000_usb_phy_enable,166 .enable = x1000_usb_phy_enable,
84 .disable = x1000_usb_phy_disable,167 .disable = x1000_usb_phy_disable,
85 .is_enabled = x1000_usb_phy_is_enabled,168 .is_enabled = x1000_usb_phy_is_enabled,
@@ -144,7 +227,6 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { · 58 unmodified lines
144 },227 },
145 },228 },
146 229
147
148 /* Custom (SoC-specific) OTG PHY */230 /* Custom (SoC-specific) OTG PHY */
149 231
150 [X1000_CLK_OTGPHY] = {232 [X1000_CLK_OTGPHY] = {
@@ -278,6 +360,19 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { · 127 unmodified lines
278 .mux = { CGU_REG_SSICDR, 30, 1 },360 .mux = { CGU_REG_SSICDR, 30, 1 },
279 },361 },
280 362
363 [X1000_CLK_EXCLK_DIV512] = {
364 "exclk_div512", CGU_CLK_FIXDIV,
365 .parents = { X1000_CLK_EXCLK },
366 .fixdiv = { 512 },
367 },
368
369 [X1000_CLK_RTC] = {
370 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
371 .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK },
372 .mux = { CGU_REG_OPCR, 2, 1},
373 .gate = { CGU_REG_CLKGR, 27 },
374 },
375
281 /* Gate-only clocks */376 /* Gate-only clocks */
282 377
283 [X1000_CLK_EMC] = {378 [X1000_CLK_EMC] = {
drivers/clk/ingenic/x1830-cgu.c+13−0
@@ -329,6 +329,19 @@ static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = { · 328 unmodified lines
329 .mux = { CGU_REG_SSICDR, 29, 1 },329 .mux = { CGU_REG_SSICDR, 29, 1 },
330 },330 },
331 331
332 [X1830_CLK_EXCLK_DIV512] = {
333 "exclk_div512", CGU_CLK_FIXDIV,
334 .parents = { X1830_CLK_EXCLK },
335 .fixdiv = { 512 },
336 },
337
338 [X1830_CLK_RTC] = {
339 "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
340 .parents = { X1830_CLK_EXCLK_DIV512, X1830_CLK_RTCLK },
341 .mux = { CGU_REG_OPCR, 2, 1},
342 .gate = { CGU_REG_CLKGR0, 29 },
343 },
344
332 /* Gate-only clocks */345 /* Gate-only clocks */
333 346
334 [X1830_CLK_EMC] = {347 [X1830_CLK_EMC] = {
drivers/clk/mmp/clk-pxa168.c+1−0
@@ -10,6 +10,7 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/clk.h>12#include <linux/clk.h>
13#include <linux/clk/mmp.h>
13#include <linux/module.h>14#include <linux/module.h>
14#include <linux/kernel.h>15#include <linux/kernel.h>
15#include <linux/spinlock.h>16#include <linux/spinlock.h>
drivers/clk/mmp/clk-pxa910.c+1−0
@@ -10,6 +10,7 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/clk.h>12#include <linux/clk.h>
13#include <linux/clk/mmp.h>
13#include <linux/module.h>14#include <linux/module.h>
14#include <linux/kernel.h>15#include <linux/kernel.h>
15#include <linux/spinlock.h>16#include <linux/spinlock.h>
drivers/clk/qcom/Kconfig+25−0
@@ -308,6 +308,15 @@ config SC_GCC_7180 · 307 unmodified lines
308 Say Y if you want to use peripheral devices such as UART, SPI,308 Say Y if you want to use peripheral devices such as UART, SPI,
309 I2C, USB, UFS, SDCC, etc.309 I2C, USB, UFS, SDCC, etc.
310 310
311config SC_LPASS_CORECC_7180
312 tristate "SC7180 LPASS Core Clock Controller"
313 select SC_GCC_7180
314 help
315 Support for the LPASS(Low Power Audio Subsystem) core clock controller
316 on SC7180 devices.
317 Say Y if you want to use LPASS clocks and power domains of the LPASS
318 core clock controller.
319
311config SC_GPUCC_7180320config SC_GPUCC_7180
312 tristate "SC7180 Graphics Clock Controller"321 tristate "SC7180 Graphics Clock Controller"
313 select SC_GCC_7180322 select SC_GCC_7180
@@ -419,6 +428,22 @@ config SM_GCC_8250 · 105 unmodified lines
419 Say Y if you want to use peripheral devices such as UART,428 Say Y if you want to use peripheral devices such as UART,
420 SPI, I2C, USB, SD/UFS, PCIe etc.429 SPI, I2C, USB, SD/UFS, PCIe etc.
421 430
431config SM_GPUCC_8150
432 tristate "SM8150 Graphics Clock Controller"
433 select SM_GCC_8150
434 help
435 Support for the graphics clock controller on SM8150 devices.
436 Say Y if you want to support graphics controller devices and
437 functionality such as 3D graphics.
438
439config SM_GPUCC_8250
440 tristate "SM8250 Graphics Clock Controller"
441 select SM_GCC_8250
442 help
443 Support for the graphics clock controller on SM8250 devices.
444 Say Y if you want to support graphics controller devices and
445 functionality such as 3D graphics.
446
422config SPMI_PMIC_CLKDIV447config SPMI_PMIC_CLKDIV
423 tristate "SPMI PMIC clkdiv Support"448 tristate "SPMI PMIC clkdiv Support"
424 depends on SPMI || COMPILE_TEST449 depends on SPMI || COMPILE_TEST
drivers/clk/qcom/Makefile+3−0
@@ -54,6 +54,7 @@ obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o · 53 unmodified lines
54obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o54obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o
55obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o55obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o
56obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o56obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o
57obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o
57obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o58obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o
58obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o59obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o
59obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o60obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o
@@ -65,6 +66,8 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o · 5 unmodified lines
65obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o66obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
66obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o67obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
67obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o68obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
69obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
70obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
68obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o71obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
69obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o72obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
70obj-$(CONFIG_QCOM_HFPLL) += hfpll.o73obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
drivers/clk/qcom/clk-alpha-pll.c+34−36
@@ -56,7 +56,6 @@ · 55 unmodified lines
56#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])56#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])
57#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])57#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])
58#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])58#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])
59#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL])
60 59
61const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {60const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
62 [CLK_ALPHA_PLL_TYPE_DEFAULT] = {61 [CLK_ALPHA_PLL_TYPE_DEFAULT] = {
@@ -102,22 +101,6 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { · 39 unmodified lines
102 [PLL_OFF_FRAC] = 0x38,101 [PLL_OFF_FRAC] = 0x38,
103 },102 },
104 [CLK_ALPHA_PLL_TYPE_TRION] = {103 [CLK_ALPHA_PLL_TYPE_TRION] = {
105 [PLL_OFF_L_VAL] = 0x04,
106 [PLL_OFF_CAL_L_VAL] = 0x08,
107 [PLL_OFF_USER_CTL] = 0x0c,
108 [PLL_OFF_USER_CTL_U] = 0x10,
109 [PLL_OFF_USER_CTL_U1] = 0x14,
110 [PLL_OFF_CONFIG_CTL] = 0x18,
111 [PLL_OFF_CONFIG_CTL_U] = 0x1c,
112 [PLL_OFF_CONFIG_CTL_U1] = 0x20,
113 [PLL_OFF_TEST_CTL] = 0x24,
114 [PLL_OFF_TEST_CTL_U] = 0x28,
115 [PLL_OFF_STATUS] = 0x30,
116 [PLL_OFF_OPMODE] = 0x38,
117 [PLL_OFF_ALPHA_VAL] = 0x40,
118 [PLL_OFF_CAL_VAL] = 0x44,
119 },
120 [CLK_ALPHA_PLL_TYPE_LUCID] = {
121 [PLL_OFF_L_VAL] = 0x04,104 [PLL_OFF_L_VAL] = 0x04,
122 [PLL_OFF_CAL_L_VAL] = 0x08,105 [PLL_OFF_CAL_L_VAL] = 0x08,
123 [PLL_OFF_USER_CTL] = 0x0c,106 [PLL_OFF_USER_CTL] = 0x0c,
@@ -156,9 +139,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); · 32 unmodified lines
156#define PLL_OUT_MASK 0x7139#define PLL_OUT_MASK 0x7
157#define PLL_RATE_MARGIN 500140#define PLL_RATE_MARGIN 500
158 141
142/* TRION PLL specific settings and offsets */
143#define TRION_PLL_CAL_VAL 0x44
144#define TRION_PCAL_DONE BIT(26)
145
159/* LUCID PLL specific settings and offsets */146/* LUCID PLL specific settings and offsets */
160#define LUCID_PLL_CAL_VAL 0x44147#define LUCID_PCAL_DONE BIT(27)
161#define LUCID_PCAL_DONE BIT(26)
162 148
163#define pll_alpha_width(p) \149#define pll_alpha_width(p) \
164 ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \150 ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
@@ -912,14 +898,14 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { · 747 unmodified lines
912};898};
913EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);899EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
914 900
915const struct clk_ops clk_trion_fixed_pll_ops = {901const struct clk_ops clk_alpha_pll_fixed_trion_ops = {
916 .enable = clk_trion_pll_enable,902 .enable = clk_trion_pll_enable,
917 .disable = clk_trion_pll_disable,903 .disable = clk_trion_pll_disable,
918 .is_enabled = clk_trion_pll_is_enabled,904 .is_enabled = clk_trion_pll_is_enabled,
919 .recalc_rate = clk_trion_pll_recalc_rate,905 .recalc_rate = clk_trion_pll_recalc_rate,
920 .round_rate = clk_alpha_pll_round_rate,906 .round_rate = clk_alpha_pll_round_rate,
921};907};
922EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops);908EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_trion_ops);
923 909
924static unsigned long910static unsigned long
925clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)911clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
@@ -1339,12 +1325,12 @@ clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, · 413 unmodified lines
1339 val << PLL_POST_DIV_SHIFT);1325 val << PLL_POST_DIV_SHIFT);
1340}1326}
1341 1327
1342const struct clk_ops clk_trion_pll_postdiv_ops = {1328const struct clk_ops clk_alpha_pll_postdiv_trion_ops = {
1343 .recalc_rate = clk_trion_pll_postdiv_recalc_rate,1329 .recalc_rate = clk_trion_pll_postdiv_recalc_rate,
1344 .round_rate = clk_trion_pll_postdiv_round_rate,1330 .round_rate = clk_trion_pll_postdiv_round_rate,
1345 .set_rate = clk_trion_pll_postdiv_set_rate,1331 .set_rate = clk_trion_pll_postdiv_set_rate,
1346};1332};
1347EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops);1333EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_trion_ops);
1348 1334
1349static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw,1335static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw,
1350 unsigned long rate, unsigned long *prate)1336 unsigned long rate, unsigned long *prate)
@@ -1399,13 +1385,13 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); · 48 unmodified lines
1399 * @regmap: register map1385 * @regmap: register map
1400 * @config: configuration to apply for pll1386 * @config: configuration to apply for pll
1401 */1387 */
1402void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,1388void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
1403 const struct alpha_pll_config *config)1389 const struct alpha_pll_config *config)
1404{1390{
1405 if (config->l)1391 if (config->l)
1406 regmap_write(regmap, PLL_L_VAL(pll), config->l);1392 regmap_write(regmap, PLL_L_VAL(pll), config->l);
1407 1393
1408 regmap_write(regmap, PLL_CAL_L_VAL(pll), LUCID_PLL_CAL_VAL);1394 regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL);
1409 1395
1410 if (config->alpha)1396 if (config->alpha)
1411 regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);1397 regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);
@@ -1458,13 +1444,13 @@ void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, · 46 unmodified lines
1458 /* Place the PLL in STANDBY mode */1444 /* Place the PLL in STANDBY mode */
1459 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);1445 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
1460}1446}
1461EXPORT_SYMBOL_GPL(clk_lucid_pll_configure);1447EXPORT_SYMBOL_GPL(clk_trion_pll_configure);
1462 1448
1463/*1449/*
1464 * The Lucid PLL requires a power-on self-calibration which happens when the1450 * The TRION PLL requires a power-on self-calibration which happens when the
1465 * PLL comes out of reset. Calibrate in case it is not completed.1451 * PLL comes out of reset. Calibrate in case it is not completed.
1466 */1452 */
1467static int alpha_pll_lucid_prepare(struct clk_hw *hw)1453static int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done)
1468{1454{
1469 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1455 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
1470 u32 regval;1456 u32 regval;
@@ -1472,7 +1458,7 @@ static int alpha_pll_lucid_prepare(struct clk_hw *hw) · 1 unmodified line
1472 1458
1473 /* Return early if calibration is not needed. */1459 /* Return early if calibration is not needed. */
1474 regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &regval);1460 regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &regval);
1475 if (regval & LUCID_PCAL_DONE)1461 if (regval & pcal_done)
1476 return 0;1462 return 0;
1477 1463
1478 /* On/off to calibrate */1464 /* On/off to calibrate */
@@ -1483,7 +1469,17 @@ static int alpha_pll_lucid_prepare(struct clk_hw *hw) · 4 unmodified lines
1483 return ret;1469 return ret;
1484}1470}
1485 1471
1486static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate,1472static int alpha_pll_trion_prepare(struct clk_hw *hw)
1473{
1474 return __alpha_pll_trion_prepare(hw, TRION_PCAL_DONE);
1475}
1476
1477static int alpha_pll_lucid_prepare(struct clk_hw *hw)
1478{
1479 return __alpha_pll_trion_prepare(hw, LUCID_PCAL_DONE);
1480}
1481
1482static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
1487 unsigned long prate)1483 unsigned long prate)
1488{1484{
1489 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1485 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
@@ -1537,25 +1533,27 @@ static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate, · 47 unmodified lines
1537 return 0;1533 return 0;
1538}1534}
1539 1535
1540const struct clk_ops clk_alpha_pll_lucid_ops = {1536const struct clk_ops clk_alpha_pll_trion_ops = {
1541 .prepare = alpha_pll_lucid_prepare,1537 .prepare = alpha_pll_trion_prepare,
1542 .enable = clk_trion_pll_enable,1538 .enable = clk_trion_pll_enable,
1543 .disable = clk_trion_pll_disable,1539 .disable = clk_trion_pll_disable,
1544 .is_enabled = clk_trion_pll_is_enabled,1540 .is_enabled = clk_trion_pll_is_enabled,
1545 .recalc_rate = clk_trion_pll_recalc_rate,1541 .recalc_rate = clk_trion_pll_recalc_rate,
1546 .round_rate = clk_alpha_pll_round_rate,1542 .round_rate = clk_alpha_pll_round_rate,
1547 .set_rate = alpha_pll_lucid_set_rate,1543 .set_rate = alpha_pll_trion_set_rate,
1548};1544};
1549EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops);1545EXPORT_SYMBOL_GPL(clk_alpha_pll_trion_ops);
1550 1546
1551const struct clk_ops clk_alpha_pll_fixed_lucid_ops = {1547const struct clk_ops clk_alpha_pll_lucid_ops = {
1548 .prepare = alpha_pll_lucid_prepare,
1552 .enable = clk_trion_pll_enable,1549 .enable = clk_trion_pll_enable,
1553 .disable = clk_trion_pll_disable,1550 .disable = clk_trion_pll_disable,
1554 .is_enabled = clk_trion_pll_is_enabled,1551 .is_enabled = clk_trion_pll_is_enabled,
1555 .recalc_rate = clk_trion_pll_recalc_rate,1552 .recalc_rate = clk_trion_pll_recalc_rate,
1556 .round_rate = clk_alpha_pll_round_rate,1553 .round_rate = clk_alpha_pll_round_rate,
1554 .set_rate = alpha_pll_trion_set_rate,
1557};1555};
1558EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_ops);1556EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops);
1559 1557
1560const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = {1558const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = {
1561 .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,1559 .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,
drivers/clk/qcom/clk-alpha-pll.h+10−5
@@ -14,7 +14,7 @@ enum { · 13 unmodified lines
14 CLK_ALPHA_PLL_TYPE_BRAMMO,14 CLK_ALPHA_PLL_TYPE_BRAMMO,
15 CLK_ALPHA_PLL_TYPE_FABIA,15 CLK_ALPHA_PLL_TYPE_FABIA,
16 CLK_ALPHA_PLL_TYPE_TRION,16 CLK_ALPHA_PLL_TYPE_TRION,
17 CLK_ALPHA_PLL_TYPE_LUCID,17 CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
18 CLK_ALPHA_PLL_TYPE_MAX,18 CLK_ALPHA_PLL_TYPE_MAX,
19};19};
20 20
@@ -134,18 +134,23 @@ extern const struct clk_ops clk_alpha_pll_fabia_ops; · 113 unmodified lines
134extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops;134extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops;
135extern const struct clk_ops clk_alpha_pll_postdiv_fabia_ops;135extern const struct clk_ops clk_alpha_pll_postdiv_fabia_ops;
136 136
137extern const struct clk_ops clk_alpha_pll_trion_ops;
138extern const struct clk_ops clk_alpha_pll_fixed_trion_ops;
139extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops;
140
137extern const struct clk_ops clk_alpha_pll_lucid_ops;141extern const struct clk_ops clk_alpha_pll_lucid_ops;
138extern const struct clk_ops clk_alpha_pll_fixed_lucid_ops;142#define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops
139extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;143extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
140 144
141void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,145void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
142 const struct alpha_pll_config *config);146 const struct alpha_pll_config *config);
143void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,147void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
144 const struct alpha_pll_config *config);148 const struct alpha_pll_config *config);
145void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,149void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
146 const struct alpha_pll_config *config);150 const struct alpha_pll_config *config);
151#define clk_lucid_pll_configure(pll, regmap, config) \
152 clk_trion_pll_configure(pll, regmap, config)
153
147 154
148extern const struct clk_ops clk_trion_fixed_pll_ops;
149extern const struct clk_ops clk_trion_pll_postdiv_ops;
150 155
151#endif156#endif
drivers/clk/qcom/gcc-sc7180.c+14−0
@@ -2251,6 +2251,19 @@ static struct clk_branch gcc_mss_q6_memnoc_axi_clk = { · 2250 unmodified lines
2251 },2251 },
2252};2252};
2253 2253
2254static struct clk_branch gcc_lpass_cfg_noc_sway_clk = {
2255 .halt_reg = 0x47018,
2256 .halt_check = BRANCH_HALT_DELAY,
2257 .clkr = {
2258 .enable_reg = 0x47018,
2259 .enable_mask = BIT(0),
2260 .hw.init = &(struct clk_init_data){
2261 .name = "gcc_lpass_cfg_noc_sway_clk",
2262 .ops = &clk_branch2_ops,
2263 },
2264 },
2265};
2266
2254static struct gdsc ufs_phy_gdsc = {2267static struct gdsc ufs_phy_gdsc = {
2255 .gdscr = 0x77004,2268 .gdscr = 0x77004,
2256 .pd = {2269 .pd = {
@@ -2428,6 +2441,7 @@ static struct clk_regmap *gcc_sc7180_clocks[] = { · 171 unmodified lines
2428 [GCC_MSS_Q6_MEMNOC_AXI_CLK] = &gcc_mss_q6_memnoc_axi_clk.clkr,2441 [GCC_MSS_Q6_MEMNOC_AXI_CLK] = &gcc_mss_q6_memnoc_axi_clk.clkr,
2429 [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,2442 [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr,
2430 [GCC_SEC_CTRL_CLK_SRC] = &gcc_sec_ctrl_clk_src.clkr,2443 [GCC_SEC_CTRL_CLK_SRC] = &gcc_sec_ctrl_clk_src.clkr,
2444 [GCC_LPASS_CFG_NOC_SWAY_CLK] = &gcc_lpass_cfg_noc_sway_clk.clkr,
2431};2445};
2432 2446
2433static const struct qcom_reset_map gcc_sc7180_resets[] = {2447static const struct qcom_reset_map gcc_sc7180_resets[] = {
drivers/clk/qcom/gcc-sdm660.c+4−0
@@ -1715,6 +1715,9 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = { · 1714 unmodified lines
1715 1715
1716static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {1716static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
1717 .halt_reg = 0x8a004,1717 .halt_reg = 0x8a004,
1718 .halt_check = BRANCH_HALT,
1719 .hwcg_reg = 0x8a004,
1720 .hwcg_bit = 1,
1718 .clkr = {1721 .clkr = {
1719 .enable_reg = 0x8a004,1722 .enable_reg = 0x8a004,
1720 .enable_mask = BIT(0),1723 .enable_mask = BIT(0),
@@ -2402,6 +2405,7 @@ static const struct qcom_reset_map gcc_sdm660_resets[] = { · 681 unmodified lines
2402 [GCC_USB_20_BCR] = { 0x2f000 },2405 [GCC_USB_20_BCR] = { 0x2f000 },
2403 [GCC_USB_30_BCR] = { 0xf000 },2406 [GCC_USB_30_BCR] = { 0xf000 },
2404 [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },2407 [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
2408 [GCC_MSS_RESTART] = { 0x79000 },
2405};2409};
2406 2410
2407static const struct regmap_config gcc_sdm660_regmap_config = {2411static const struct regmap_config gcc_sdm660_regmap_config = {
drivers/clk/qcom/gcc-sm8150.c+10−16
@@ -34,14 +34,8 @@ enum { · 33 unmodified lines
34 P_SLEEP_CLK,34 P_SLEEP_CLK,
35};35};
36 36
37static const struct pll_vco trion_vco[] = {
38 { 249600000, 2000000000, 0 },
39};
40
41static struct clk_alpha_pll gpll0 = {37static struct clk_alpha_pll gpll0 = {
42 .offset = 0x0,38 .offset = 0x0,
43 .vco_table = trion_vco,
44 .num_vco = ARRAY_SIZE(trion_vco),
45 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],39 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
46 .clkr = {40 .clkr = {
47 .enable_reg = 0x52000,41 .enable_reg = 0x52000,
@@ -53,7 +47,7 @@ static struct clk_alpha_pll gpll0 = { · 5 unmodified lines
53 .name = "bi_tcxo",47 .name = "bi_tcxo",
54 },48 },
55 .num_parents = 1,49 .num_parents = 1,
56 .ops = &clk_trion_fixed_pll_ops,50 .ops = &clk_alpha_pll_fixed_trion_ops,
57 },51 },
58 },52 },
59};53};
@@ -79,14 +73,12 @@ static struct clk_alpha_pll_postdiv gpll0_out_even = { · 19 unmodified lines
79 .hw = &gpll0.clkr.hw,73 .hw = &gpll0.clkr.hw,
80 },74 },
81 .num_parents = 1,75 .num_parents = 1,
82 .ops = &clk_trion_pll_postdiv_ops,76 .ops = &clk_alpha_pll_postdiv_trion_ops,
83 },77 },
84};78};
85 79
86static struct clk_alpha_pll gpll7 = {80static struct clk_alpha_pll gpll7 = {
87 .offset = 0x1a000,81 .offset = 0x1a000,
88 .vco_table = trion_vco,
89 .num_vco = ARRAY_SIZE(trion_vco),
90 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],82 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
91 .clkr = {83 .clkr = {
92 .enable_reg = 0x52000,84 .enable_reg = 0x52000,
@@ -98,15 +90,13 @@ static struct clk_alpha_pll gpll7 = { · 5 unmodified lines
98 .name = "bi_tcxo",90 .name = "bi_tcxo",
99 },91 },
100 .num_parents = 1,92 .num_parents = 1,
101 .ops = &clk_trion_fixed_pll_ops,93 .ops = &clk_alpha_pll_fixed_trion_ops,
102 },94 },
103 },95 },
104};96};
105 97
106static struct clk_alpha_pll gpll9 = {98static struct clk_alpha_pll gpll9 = {
107 .offset = 0x1c000,99 .offset = 0x1c000,
108 .vco_table = trion_vco,
109 .num_vco = ARRAY_SIZE(trion_vco),
110 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],100 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
111 .clkr = {101 .clkr = {
112 .enable_reg = 0x52000,102 .enable_reg = 0x52000,
@@ -118,7 +108,7 @@ static struct clk_alpha_pll gpll9 = { · 5 unmodified lines
118 .name = "bi_tcxo",108 .name = "bi_tcxo",
119 },109 },
120 .num_parents = 1,110 .num_parents = 1,
121 .ops = &clk_trion_fixed_pll_ops,111 .ops = &clk_alpha_pll_fixed_trion_ops,
122 },112 },
123 },113 },
124};114};
@@ -1617,6 +1607,7 @@ static struct clk_branch gcc_gpu_cfg_ahb_clk = { · 1492 unmodified lines
1617};1607};
1618 1608
1619static struct clk_branch gcc_gpu_gpll0_clk_src = {1609static struct clk_branch gcc_gpu_gpll0_clk_src = {
1610 .halt_check = BRANCH_HALT_SKIP,
1620 .clkr = {1611 .clkr = {
1621 .enable_reg = 0x52004,1612 .enable_reg = 0x52004,
1622 .enable_mask = BIT(15),1613 .enable_mask = BIT(15),
@@ -1632,13 +1623,14 @@ static struct clk_branch gcc_gpu_gpll0_clk_src = { · 9 unmodified lines
1632};1623};
1633 1624
1634static struct clk_branch gcc_gpu_gpll0_div_clk_src = {1625static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
1626 .halt_check = BRANCH_HALT_SKIP,
1635 .clkr = {1627 .clkr = {
1636 .enable_reg = 0x52004,1628 .enable_reg = 0x52004,
1637 .enable_mask = BIT(16),1629 .enable_mask = BIT(16),
1638 .hw.init = &(struct clk_init_data){1630 .hw.init = &(struct clk_init_data){
1639 .name = "gcc_gpu_gpll0_div_clk_src",1631 .name = "gcc_gpu_gpll0_div_clk_src",
1640 .parent_hws = (const struct clk_hw *[]){1632 .parent_hws = (const struct clk_hw *[]){
1641 &gcc_gpu_gpll0_clk_src.clkr.hw },1633 &gpll0_out_even.clkr.hw },
1642 .num_parents = 1,1634 .num_parents = 1,
1643 .flags = CLK_SET_RATE_PARENT,1635 .flags = CLK_SET_RATE_PARENT,
1644 .ops = &clk_branch2_ops,1636 .ops = &clk_branch2_ops,
@@ -1729,6 +1721,7 @@ static struct clk_branch gcc_npu_cfg_ahb_clk = { · 84 unmodified lines
1729};1721};
1730 1722
1731static struct clk_branch gcc_npu_gpll0_clk_src = {1723static struct clk_branch gcc_npu_gpll0_clk_src = {
1724 .halt_check = BRANCH_HALT_SKIP,
1732 .clkr = {1725 .clkr = {
1733 .enable_reg = 0x52004,1726 .enable_reg = 0x52004,
1734 .enable_mask = BIT(18),1727 .enable_mask = BIT(18),
@@ -1744,13 +1737,14 @@ static struct clk_branch gcc_npu_gpll0_clk_src = { · 9 unmodified lines
1744};1737};
1745 1738
1746static struct clk_branch gcc_npu_gpll0_div_clk_src = {1739static struct clk_branch gcc_npu_gpll0_div_clk_src = {
1740 .halt_check = BRANCH_HALT_SKIP,
1747 .clkr = {1741 .clkr = {
1748 .enable_reg = 0x52004,1742 .enable_reg = 0x52004,
1749 .enable_mask = BIT(19),1743 .enable_mask = BIT(19),
1750 .hw.init = &(struct clk_init_data){1744 .hw.init = &(struct clk_init_data){
1751 .name = "gcc_npu_gpll0_div_clk_src",1745 .name = "gcc_npu_gpll0_div_clk_src",
1752 .parent_hws = (const struct clk_hw *[]){1746 .parent_hws = (const struct clk_hw *[]){
1753 &gcc_npu_gpll0_clk_src.clkr.hw },1747 &gpll0_out_even.clkr.hw },
1754 .num_parents = 1,1748 .num_parents = 1,
1755 .flags = CLK_SET_RATE_PARENT,1749 .flags = CLK_SET_RATE_PARENT,
1756 .ops = &clk_branch2_ops,1750 .ops = &clk_branch2_ops,
drivers/clk/qcom/gdsc.c+39−0
@@ -6,6 +6,7 @@ · 5 unmodified lines
6#include <linux/bitops.h>6#include <linux/bitops.h>
7#include <linux/delay.h>7#include <linux/delay.h>
8#include <linux/err.h>8#include <linux/err.h>
9#include <linux/export.h>
9#include <linux/jiffies.h>10#include <linux/jiffies.h>
10#include <linux/kernel.h>11#include <linux/kernel.h>
11#include <linux/ktime.h>12#include <linux/ktime.h>
@@ -29,6 +30,7 @@ · 17 unmodified lines
29/* CFG_GDSCR */30/* CFG_GDSCR */
30#define GDSC_POWER_UP_COMPLETE BIT(16)31#define GDSC_POWER_UP_COMPLETE BIT(16)
31#define GDSC_POWER_DOWN_COMPLETE BIT(15)32#define GDSC_POWER_DOWN_COMPLETE BIT(15)
33#define GDSC_RETAIN_FF_ENABLE BIT(11)
32#define CFG_GDSCR_OFFSET 0x434#define CFG_GDSCR_OFFSET 0x4
33 35
34/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */36/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
@@ -216,6 +218,14 @@ static inline void gdsc_assert_reset_aon(struct gdsc *sc) · 181 unmodified lines
216 regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,218 regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
217 GMEM_RESET_MASK, 0);219 GMEM_RESET_MASK, 0);
218}220}
221
222static void gdsc_retain_ff_on(struct gdsc *sc)
223{
224 u32 mask = GDSC_RETAIN_FF_ENABLE;
225
226 regmap_update_bits(sc->regmap, sc->gdscr, mask, mask);
227}
228
219static int gdsc_enable(struct generic_pm_domain *domain)229static int gdsc_enable(struct generic_pm_domain *domain)
220{230{
221 struct gdsc *sc = domain_to_gdsc(domain);231 struct gdsc *sc = domain_to_gdsc(domain);
@@ -268,6 +278,9 @@ static int gdsc_enable(struct generic_pm_domain *domain) · 46 unmodified lines
268 udelay(1);278 udelay(1);
269 }279 }
270 280
281 if (sc->flags & RETAIN_FF_ENABLE)
282 gdsc_retain_ff_on(sc);
283
271 return 0;284 return 0;
272}285}
273 286
@@ -433,3 +446,29 @@ void gdsc_unregister(struct gdsc_desc *desc) · 159 unmodified lines
433 }446 }
434 of_genpd_del_provider(dev->of_node);447 of_genpd_del_provider(dev->of_node);
435}448}
449
450/*
451 * On SDM845+ the GPU GX domain is *almost* entirely controlled by the GMU
452 * running in the CX domain so the CPU doesn't need to know anything about the
453 * GX domain EXCEPT....
454 *
455 * Hardware constraints dictate that the GX be powered down before the CX. If
456 * the GMU crashes it could leave the GX on. In order to successfully bring back
457 * the device the CPU needs to disable the GX headswitch. There being no sane
458 * way to reach in and touch that register from deep inside the GPU driver we
459 * need to set up the infrastructure to be able to ensure that the GPU can
460 * ensure that the GX is off during this super special case. We do this by
461 * defining a GX gdsc with a dummy enable function and a "default" disable
462 * function.
463 *
464 * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU
465 * driver. During power up, nothing will happen from the CPU (and the GMU will
466 * power up normally but during power down this will ensure that the GX domain
467 * is *really* off - this gives us a semi standard way of doing what we need.
468 */
469int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain)
470{
471 /* Do nothing but give genpd the impression that we were successful */
472 return 0;
473}
474EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable);
drivers/clk/qcom/gdsc.h+2−0
@@ -50,6 +50,7 @@ struct gdsc { · 49 unmodified lines
50#define AON_RESET BIT(4)50#define AON_RESET BIT(4)
51#define POLL_CFG_GDSCR BIT(5)51#define POLL_CFG_GDSCR BIT(5)
52#define ALWAYS_ON BIT(6)52#define ALWAYS_ON BIT(6)
53#define RETAIN_FF_ENABLE BIT(7)
53 struct reset_controller_dev *rcdev;54 struct reset_controller_dev *rcdev;
54 unsigned int *resets;55 unsigned int *resets;
55 unsigned int reset_count;56 unsigned int reset_count;
@@ -68,6 +69,7 @@ struct gdsc_desc { · 12 unmodified lines
68int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *,69int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *,
69 struct regmap *);70 struct regmap *);
70void gdsc_unregister(struct gdsc_desc *desc);71void gdsc_unregister(struct gdsc_desc *desc);
72int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain);
71#else73#else
72static inline int gdsc_register(struct gdsc_desc *desc,74static inline int gdsc_register(struct gdsc_desc *desc,
73 struct reset_controller_dev *rcdev,75 struct reset_controller_dev *rcdev,
drivers/clk/qcom/gpucc-sc7180.c+1−26
@@ -170,37 +170,12 @@ static struct gdsc cx_gdsc = { · 169 unmodified lines
170 .flags = VOTABLE,170 .flags = VOTABLE,
171};171};
172 172
173/*
174 * On SC7180 the GPU GX domain is *almost* entirely controlled by the GMU
175 * running in the CX domain so the CPU doesn't need to know anything about the
176 * GX domain EXCEPT....
177 *
178 * Hardware constraints dictate that the GX be powered down before the CX. If
179 * the GMU crashes it could leave the GX on. In order to successfully bring back
180 * the device the CPU needs to disable the GX headswitch. There being no sane
181 * way to reach in and touch that register from deep inside the GPU driver we
182 * need to set up the infrastructure to be able to ensure that the GPU can
183 * ensure that the GX is off during this super special case. We do this by
184 * defining a GX gdsc with a dummy enable function and a "default" disable
185 * function.
186 *
187 * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU
188 * driver. During power up, nothing will happen from the CPU (and the GMU will
189 * power up normally but during power down this will ensure that the GX domain
190 * is *really* off - this gives us a semi standard way of doing what we need.
191 */
192static int gx_gdsc_enable(struct generic_pm_domain *domain)
193{
194 /* Do nothing but give genpd the impression that we were successful */
195 return 0;
196}
197
198static struct gdsc gx_gdsc = {173static struct gdsc gx_gdsc = {
199 .gdscr = 0x100c,174 .gdscr = 0x100c,
200 .clamp_io_ctrl = 0x1508,175 .clamp_io_ctrl = 0x1508,
201 .pd = {176 .pd = {
202 .name = "gx_gdsc",177 .name = "gx_gdsc",
203 .power_on = gx_gdsc_enable,178 .power_on = gdsc_gx_do_nothing_enable,
204 },179 },
205 .pwrsts = PWRSTS_OFF_ON,180 .pwrsts = PWRSTS_OFF_ON,
206 .flags = CLAMP_IO,181 .flags = CLAMP_IO,
drivers/clk/qcom/gpucc-sdm845.c+1−26
@@ -131,37 +131,12 @@ static struct gdsc gpu_cx_gdsc = { · 130 unmodified lines
131 .flags = VOTABLE,131 .flags = VOTABLE,
132};132};
133 133
134/*
135 * On SDM845 the GPU GX domain is *almost* entirely controlled by the GMU
136 * running in the CX domain so the CPU doesn't need to know anything about the
137 * GX domain EXCEPT....
138 *
139 * Hardware constraints dictate that the GX be powered down before the CX. If
140 * the GMU crashes it could leave the GX on. In order to successfully bring back
141 * the device the CPU needs to disable the GX headswitch. There being no sane
142 * way to reach in and touch that register from deep inside the GPU driver we
143 * need to set up the infrastructure to be able to ensure that the GPU can
144 * ensure that the GX is off during this super special case. We do this by
145 * defining a GX gdsc with a dummy enable function and a "default" disable
146 * function.
147 *
148 * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU
149 * driver. During power up, nothing will happen from the CPU (and the GMU will
150 * power up normally but during power down this will ensure that the GX domain
151 * is *really* off - this gives us a semi standard way of doing what we need.
152 */
153static int gx_gdsc_enable(struct generic_pm_domain *domain)
154{
155 /* Do nothing but give genpd the impression that we were successful */
156 return 0;
157}
158
159static struct gdsc gpu_gx_gdsc = {134static struct gdsc gpu_gx_gdsc = {
160 .gdscr = 0x100c,135 .gdscr = 0x100c,
161 .clamp_io_ctrl = 0x1508,136 .clamp_io_ctrl = 0x1508,
162 .pd = {137 .pd = {
163 .name = "gpu_gx_gdsc",138 .name = "gpu_gx_gdsc",
164 .power_on = gx_gdsc_enable,139 .power_on = gdsc_gx_do_nothing_enable,
165 },140 },
166 .pwrsts = PWRSTS_OFF_ON,141 .pwrsts = PWRSTS_OFF_ON,
167 .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,142 .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
drivers/clk/qcom/gpucc-sm8150.c+320−0
@@ -0,0 +1,320 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/module.h>
8#include <linux/platform_device.h>
9#include <linux/regmap.h>
10
11#include <dt-bindings/clock/qcom,gpucc-sm8150.h>
12
13#include "common.h"
14#include "clk-alpha-pll.h"
15#include "clk-branch.h"
16#include "clk-pll.h"
17#include "clk-rcg.h"
18#include "clk-regmap.h"
19#include "reset.h"
20#include "gdsc.h"
21
22enum {
23 P_BI_TCXO,
24 P_CORE_BI_PLL_TEST_SE,
25 P_GPLL0_OUT_MAIN,
26 P_GPLL0_OUT_MAIN_DIV,
27 P_GPU_CC_PLL1_OUT_MAIN,
28};
29
30static const struct pll_vco trion_vco[] = {
31 { 249600000, 2000000000, 0 },
32};
33
34static struct alpha_pll_config gpu_cc_pll1_config = {
35 .l = 0x1a,
36 .alpha = 0xaaa,
37 .config_ctl_val = 0x20485699,
38 .config_ctl_hi_val = 0x00002267,
39 .config_ctl_hi1_val = 0x00000024,
40 .test_ctl_val = 0x00000000,
41 .test_ctl_hi_val = 0x00000002,
42 .test_ctl_hi1_val = 0x00000000,
43 .user_ctl_val = 0x00000000,
44 .user_ctl_hi_val = 0x00000805,
45 .user_ctl_hi1_val = 0x000000d0,
46};
47
48static struct clk_alpha_pll gpu_cc_pll1 = {
49 .offset = 0x100,
50 .vco_table = trion_vco,
51 .num_vco = ARRAY_SIZE(trion_vco),
52 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
53 .clkr = {
54 .hw.init = &(struct clk_init_data){
55 .name = "gpu_cc_pll1",
56 .parent_data = &(const struct clk_parent_data){
57 .fw_name = "bi_tcxo",
58 },
59 .num_parents = 1,
60 .ops = &clk_alpha_pll_trion_ops,
61 },
62 },
63};
64
65static const struct parent_map gpu_cc_parent_map_0[] = {
66 { P_BI_TCXO, 0 },
67 { P_GPU_CC_PLL1_OUT_MAIN, 3 },
68 { P_GPLL0_OUT_MAIN, 5 },
69 { P_GPLL0_OUT_MAIN_DIV, 6 },
70};
71
72static const struct clk_parent_data gpu_cc_parent_data_0[] = {
73 { .fw_name = "bi_tcxo" },
74 { .hw = &gpu_cc_pll1.clkr.hw },
75 { .fw_name = "gcc_gpu_gpll0_clk_src" },
76 { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
77};
78
79static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
80 F(19200000, P_BI_TCXO, 1, 0, 0),
81 F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
82 F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
83 { }
84};
85
86static struct clk_rcg2 gpu_cc_gmu_clk_src = {
87 .cmd_rcgr = 0x1120,
88 .mnd_width = 0,
89 .hid_width = 5,
90 .parent_map = gpu_cc_parent_map_0,
91 .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
92 .clkr.hw.init = &(struct clk_init_data){
93 .name = "gpu_cc_gmu_clk_src",
94 .parent_data = gpu_cc_parent_data_0,
95 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
96 .flags = CLK_SET_RATE_PARENT,
97 .ops = &clk_rcg2_ops,
98 },
99};
100
101static struct clk_branch gpu_cc_ahb_clk = {
102 .halt_reg = 0x1078,
103 .halt_check = BRANCH_HALT_DELAY,
104 .clkr = {
105 .enable_reg = 0x1078,
106 .enable_mask = BIT(0),
107 .hw.init = &(struct clk_init_data){
108 .name = "gpu_cc_ahb_clk",
109 .ops = &clk_branch2_ops,
110 },
111 },
112};
113
114static struct clk_branch gpu_cc_crc_ahb_clk = {
115 .halt_reg = 0x107c,
116 .halt_check = BRANCH_HALT,
117 .clkr = {
118 .enable_reg = 0x107c,
119 .enable_mask = BIT(0),
120 .hw.init = &(struct clk_init_data){
121 .name = "gpu_cc_crc_ahb_clk",
122 .ops = &clk_branch2_ops,
123 },
124 },
125};
126
127static struct clk_branch gpu_cc_cx_apb_clk = {
128 .halt_reg = 0x1088,
129 .halt_check = BRANCH_HALT,
130 .clkr = {
131 .enable_reg = 0x1088,
132 .enable_mask = BIT(0),
133 .hw.init = &(struct clk_init_data){
134 .name = "gpu_cc_cx_apb_clk",
135 .ops = &clk_branch2_ops,
136 },
137 },
138};
139
140static struct clk_branch gpu_cc_cx_gmu_clk = {
141 .halt_reg = 0x1098,
142 .halt_check = BRANCH_HALT,
143 .clkr = {
144 .enable_reg = 0x1098,
145 .enable_mask = BIT(0),
146 .hw.init = &(struct clk_init_data){
147 .name = "gpu_cc_cx_gmu_clk",
148 .parent_data = &(const struct clk_parent_data){
149 .hw = &gpu_cc_gmu_clk_src.clkr.hw,
150 },
151 .num_parents = 1,
152 .flags = CLK_SET_RATE_PARENT,
153 .ops = &clk_branch2_ops,
154 },
155 },
156};
157
158static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
159 .halt_reg = 0x108c,
160 .halt_check = BRANCH_HALT,
161 .clkr = {
162 .enable_reg = 0x108c,
163 .enable_mask = BIT(0),
164 .hw.init = &(struct clk_init_data){
165 .name = "gpu_cc_cx_snoc_dvm_clk",
166 .ops = &clk_branch2_ops,
167 },
168 },
169};
170
171static struct clk_branch gpu_cc_cxo_aon_clk = {
172 .halt_reg = 0x1004,
173 .halt_check = BRANCH_HALT,
174 .clkr = {
175 .enable_reg = 0x1004,
176 .enable_mask = BIT(0),
177 .hw.init = &(struct clk_init_data){
178 .name = "gpu_cc_cxo_aon_clk",
179 .ops = &clk_branch2_ops,
180 },
181 },
182};
183
184static struct clk_branch gpu_cc_cxo_clk = {
185 .halt_reg = 0x109c,
186 .halt_check = BRANCH_HALT,
187 .clkr = {
188 .enable_reg = 0x109c,
189 .enable_mask = BIT(0),
190 .hw.init = &(struct clk_init_data){
191 .name = "gpu_cc_cxo_clk",
192 .ops = &clk_branch2_ops,
193 },
194 },
195};
196
197static struct clk_branch gpu_cc_gx_gmu_clk = {
198 .halt_reg = 0x1064,
199 .halt_check = BRANCH_HALT,
200 .clkr = {
201 .enable_reg = 0x1064,
202 .enable_mask = BIT(0),
203 .hw.init = &(struct clk_init_data){
204 .name = "gpu_cc_gx_gmu_clk",
205 .parent_data = &(const struct clk_parent_data){
206 .hw = &gpu_cc_gmu_clk_src.clkr.hw,
207 },
208 .num_parents = 1,
209 .flags = CLK_SET_RATE_PARENT,
210 .ops = &clk_branch2_ops,
211 },
212 },
213};
214
215static struct gdsc gpu_cx_gdsc = {
216 .gdscr = 0x106c,
217 .gds_hw_ctrl = 0x1540,
218 .pd = {
219 .name = "gpu_cx_gdsc",
220 },
221 .pwrsts = PWRSTS_OFF_ON,
222 .flags = VOTABLE,
223};
224
225static struct gdsc gpu_gx_gdsc = {
226 .gdscr = 0x100c,
227 .clamp_io_ctrl = 0x1508,
228 .pd = {
229 .name = "gpu_gx_gdsc",
230 .power_on = gdsc_gx_do_nothing_enable,
231 },
232 .pwrsts = PWRSTS_OFF_ON,
233 .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
234};
235
236static struct clk_regmap *gpu_cc_sm8150_clocks[] = {
237 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
238 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
239 [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
240 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
241 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
242 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
243 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
244 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
245 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
246 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
247};
248
249static const struct qcom_reset_map gpu_cc_sm8150_resets[] = {
250 [GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
251 [GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
252 [GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
253 [GPUCC_GPU_CC_SPDM_BCR] = { 0x1110 },
254 [GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
255};
256
257static struct gdsc *gpu_cc_sm8150_gdscs[] = {
258 [GPU_CX_GDSC] = &gpu_cx_gdsc,
259 [GPU_GX_GDSC] = &gpu_gx_gdsc,
260};
261
262static const struct regmap_config gpu_cc_sm8150_regmap_config = {
263 .reg_bits = 32,
264 .reg_stride = 4,
265 .val_bits = 32,
266 .max_register = 0x8008,
267 .fast_io = true,
268};
269
270static const struct qcom_cc_desc gpu_cc_sm8150_desc = {
271 .config = &gpu_cc_sm8150_regmap_config,
272 .clks = gpu_cc_sm8150_clocks,
273 .num_clks = ARRAY_SIZE(gpu_cc_sm8150_clocks),
274 .resets = gpu_cc_sm8150_resets,
275 .num_resets = ARRAY_SIZE(gpu_cc_sm8150_resets),
276 .gdscs = gpu_cc_sm8150_gdscs,
277 .num_gdscs = ARRAY_SIZE(gpu_cc_sm8150_gdscs),
278};
279
280static const struct of_device_id gpu_cc_sm8150_match_table[] = {
281 { .compatible = "qcom,sm8150-gpucc" },
282 { }
283};
284MODULE_DEVICE_TABLE(of, gpu_cc_sm8150_match_table);
285
286static int gpu_cc_sm8150_probe(struct platform_device *pdev)
287{
288 struct regmap *regmap;
289
290 regmap = qcom_cc_map(pdev, &gpu_cc_sm8150_desc);
291 if (IS_ERR(regmap))
292 return PTR_ERR(regmap);
293
294 clk_trion_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
295
296 return qcom_cc_really_probe(pdev, &gpu_cc_sm8150_desc, regmap);
297}
298
299static struct platform_driver gpu_cc_sm8150_driver = {
300 .probe = gpu_cc_sm8150_probe,
301 .driver = {
302 .name = "sm8150-gpucc",
303 .of_match_table = gpu_cc_sm8150_match_table,
304 },
305};
306
307static int __init gpu_cc_sm8150_init(void)
308{
309 return platform_driver_register(&gpu_cc_sm8150_driver);
310}
311subsys_initcall(gpu_cc_sm8150_init);
312
313static void __exit gpu_cc_sm8150_exit(void)
314{
315 platform_driver_unregister(&gpu_cc_sm8150_driver);
316}
317module_exit(gpu_cc_sm8150_exit);
318
319MODULE_DESCRIPTION("QTI GPUCC SM8150 Driver");
320MODULE_LICENSE("GPL v2");
drivers/clk/qcom/gpucc-sm8250.c+348−0
@@ -0,0 +1,348 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/module.h>
8#include <linux/platform_device.h>
9#include <linux/regmap.h>
10
11#include <dt-bindings/clock/qcom,gpucc-sm8250.h>
12
13#include "common.h"
14#include "clk-alpha-pll.h"
15#include "clk-branch.h"
16#include "clk-pll.h"
17#include "clk-rcg.h"
18#include "clk-regmap.h"
19#include "reset.h"
20#include "gdsc.h"
21
22#define CX_GMU_CBCR_SLEEP_MASK 0xf
23#define CX_GMU_CBCR_SLEEP_SHIFT 4
24#define CX_GMU_CBCR_WAKE_MASK 0xf
25#define CX_GMU_CBCR_WAKE_SHIFT 8
26
27enum {
28 P_BI_TCXO,
29 P_CORE_BI_PLL_TEST_SE,
30 P_GPLL0_OUT_MAIN,
31 P_GPLL0_OUT_MAIN_DIV,
32 P_GPU_CC_PLL0_OUT_MAIN,
33 P_GPU_CC_PLL1_OUT_MAIN,
34};
35
36static struct pll_vco lucid_vco[] = {
37 { 249600000, 2000000000, 0 },
38};
39
40static const struct alpha_pll_config gpu_cc_pll1_config = {
41 .l = 0x1a,
42 .alpha = 0xaaa,
43 .config_ctl_val = 0x20485699,
44 .config_ctl_hi_val = 0x00002261,
45 .config_ctl_hi1_val = 0x029a699c,
46 .user_ctl_val = 0x00000000,
47 .user_ctl_hi_val = 0x00000805,
48 .user_ctl_hi1_val = 0x00000000,
49};
50
51static struct clk_alpha_pll gpu_cc_pll1 = {
52 .offset = 0x100,
53 .vco_table = lucid_vco,
54 .num_vco = ARRAY_SIZE(lucid_vco),
55 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
56 .clkr = {
57 .hw.init = &(struct clk_init_data){
58 .name = "gpu_cc_pll1",
59 .parent_data = &(const struct clk_parent_data){
60 .fw_name = "bi_tcxo",
61 },
62 .num_parents = 1,
63 .ops = &clk_alpha_pll_lucid_ops,
64 },
65 },
66};
67
68static const struct parent_map gpu_cc_parent_map_0[] = {
69 { P_BI_TCXO, 0 },
70 { P_GPU_CC_PLL1_OUT_MAIN, 3 },
71 { P_GPLL0_OUT_MAIN, 5 },
72 { P_GPLL0_OUT_MAIN_DIV, 6 },
73};
74
75static const struct clk_parent_data gpu_cc_parent_data_0[] = {
76 { .fw_name = "bi_tcxo" },
77 { .hw = &gpu_cc_pll1.clkr.hw },
78 { .fw_name = "gcc_gpu_gpll0_clk_src" },
79 { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
80};
81
82static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
83 F(19200000, P_BI_TCXO, 1, 0, 0),
84 F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
85 F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
86 { }
87};
88
89static struct clk_rcg2 gpu_cc_gmu_clk_src = {
90 .cmd_rcgr = 0x1120,
91 .mnd_width = 0,
92 .hid_width = 5,
93 .parent_map = gpu_cc_parent_map_0,
94 .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
95 .clkr.hw.init = &(struct clk_init_data){
96 .name = "gpu_cc_gmu_clk_src",
97 .parent_data = gpu_cc_parent_data_0,
98 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
99 .flags = CLK_SET_RATE_PARENT,
100 .ops = &clk_rcg2_ops,
101 },
102};
103
104static struct clk_branch gpu_cc_ahb_clk = {
105 .halt_reg = 0x1078,
106 .halt_check = BRANCH_HALT_DELAY,
107 .clkr = {
108 .enable_reg = 0x1078,
109 .enable_mask = BIT(0),
110 .hw.init = &(struct clk_init_data){
111 .name = "gpu_cc_ahb_clk",
112 .ops = &clk_branch2_ops,
113 },
114 },
115};
116
117static struct clk_branch gpu_cc_crc_ahb_clk = {
118 .halt_reg = 0x107c,
119 .halt_check = BRANCH_HALT_VOTED,
120 .clkr = {
121 .enable_reg = 0x107c,
122 .enable_mask = BIT(0),
123 .hw.init = &(struct clk_init_data){
124 .name = "gpu_cc_crc_ahb_clk",
125 .ops = &clk_branch2_ops,
126 },
127 },
128};
129
130static struct clk_branch gpu_cc_cx_apb_clk = {
131 .halt_reg = 0x1088,
132 .halt_check = BRANCH_HALT_VOTED,
133 .clkr = {
134 .enable_reg = 0x1088,
135 .enable_mask = BIT(0),
136 .hw.init = &(struct clk_init_data){
137 .name = "gpu_cc_cx_apb_clk",
138 .ops = &clk_branch2_ops,
139 },
140 },
141};
142
143static struct clk_branch gpu_cc_cx_gmu_clk = {
144 .halt_reg = 0x1098,
145 .halt_check = BRANCH_HALT,
146 .clkr = {
147 .enable_reg = 0x1098,
148 .enable_mask = BIT(0),
149 .hw.init = &(struct clk_init_data){
150 .name = "gpu_cc_cx_gmu_clk",
151 .parent_data = &(const struct clk_parent_data){
152 .hw = &gpu_cc_gmu_clk_src.clkr.hw,
153 },
154 .num_parents = 1,
155 .flags = CLK_SET_RATE_PARENT,
156 .ops = &clk_branch2_ops,
157 },
158 },
159};
160
161static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
162 .halt_reg = 0x108c,
163 .halt_check = BRANCH_HALT_VOTED,
164 .clkr = {
165 .enable_reg = 0x108c,
166 .enable_mask = BIT(0),
167 .hw.init = &(struct clk_init_data){
168 .name = "gpu_cc_cx_snoc_dvm_clk",
169 .ops = &clk_branch2_ops,
170 },
171 },
172};
173
174static struct clk_branch gpu_cc_cxo_aon_clk = {
175 .halt_reg = 0x1004,
176 .halt_check = BRANCH_HALT_VOTED,
177 .clkr = {
178 .enable_reg = 0x1004,
179 .enable_mask = BIT(0),
180 .hw.init = &(struct clk_init_data){
181 .name = "gpu_cc_cxo_aon_clk",
182 .ops = &clk_branch2_ops,
183 },
184 },
185};
186
187static struct clk_branch gpu_cc_cxo_clk = {
188 .halt_reg = 0x109c,
189 .halt_check = BRANCH_HALT,
190 .clkr = {
191 .enable_reg = 0x109c,
192 .enable_mask = BIT(0),
193 .hw.init = &(struct clk_init_data){
194 .name = "gpu_cc_cxo_clk",
195 .ops = &clk_branch2_ops,
196 },
197 },
198};
199
200static struct clk_branch gpu_cc_gx_gmu_clk = {
201 .halt_reg = 0x1064,
202 .halt_check = BRANCH_HALT,
203 .clkr = {
204 .enable_reg = 0x1064,
205 .enable_mask = BIT(0),
206 .hw.init = &(struct clk_init_data){
207 .name = "gpu_cc_gx_gmu_clk",
208 .parent_data = &(const struct clk_parent_data){
209 .hw = &gpu_cc_gmu_clk_src.clkr.hw,
210 },
211 .num_parents = 1,
212 .flags = CLK_SET_RATE_PARENT,
213 .ops = &clk_branch2_ops,
214 },
215 },
216};
217
218static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
219 .halt_reg = 0x5000,
220 .halt_check = BRANCH_VOTED,
221 .clkr = {
222 .enable_reg = 0x5000,
223 .enable_mask = BIT(0),
224 .hw.init = &(struct clk_init_data){
225 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
226 .ops = &clk_branch2_ops,
227 },
228 },
229};
230
231static struct gdsc gpu_cx_gdsc = {
232 .gdscr = 0x106c,
233 .gds_hw_ctrl = 0x1540,
234 .pd = {
235 .name = "gpu_cx_gdsc",
236 },
237 .pwrsts = PWRSTS_OFF_ON,
238 .flags = VOTABLE,
239};
240
241static struct gdsc gpu_gx_gdsc = {
242 .gdscr = 0x100c,
243 .clamp_io_ctrl = 0x1508,
244 .pd = {
245 .name = "gpu_gx_gdsc",
246 .power_on = gdsc_gx_do_nothing_enable,
247 },
248 .pwrsts = PWRSTS_OFF_ON,
249 .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
250};
251
252static struct clk_regmap *gpu_cc_sm8250_clocks[] = {
253 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
254 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
255 [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
256 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
257 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
258 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
259 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
260 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
261 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
262 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
263 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
264};
265
266static const struct qcom_reset_map gpu_cc_sm8250_resets[] = {
267 [GPUCC_GPU_CC_ACD_BCR] = { 0x1160 },
268 [GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
269 [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
270 [GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
271 [GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
272 [GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
273};
274
275static struct gdsc *gpu_cc_sm8250_gdscs[] = {
276 [GPU_CX_GDSC] = &gpu_cx_gdsc,
277 [GPU_GX_GDSC] = &gpu_gx_gdsc,
278};
279
280static const struct regmap_config gpu_cc_sm8250_regmap_config = {
281 .reg_bits = 32,
282 .reg_stride = 4,
283 .val_bits = 32,
284 .max_register = 0x8008,
285 .fast_io = true,
286};
287
288static const struct qcom_cc_desc gpu_cc_sm8250_desc = {
289 .config = &gpu_cc_sm8250_regmap_config,
290 .clks = gpu_cc_sm8250_clocks,
291 .num_clks = ARRAY_SIZE(gpu_cc_sm8250_clocks),
292 .resets = gpu_cc_sm8250_resets,
293 .num_resets = ARRAY_SIZE(gpu_cc_sm8250_resets),
294 .gdscs = gpu_cc_sm8250_gdscs,
295 .num_gdscs = ARRAY_SIZE(gpu_cc_sm8250_gdscs),
296};
297
298static const struct of_device_id gpu_cc_sm8250_match_table[] = {
299 { .compatible = "qcom,sm8250-gpucc" },
300 { }
301};
302MODULE_DEVICE_TABLE(of, gpu_cc_sm8250_match_table);
303
304static int gpu_cc_sm8250_probe(struct platform_device *pdev)
305{
306 struct regmap *regmap;
307 unsigned int value, mask;
308
309 regmap = qcom_cc_map(pdev, &gpu_cc_sm8250_desc);
310 if (IS_ERR(regmap))
311 return PTR_ERR(regmap);
312
313 clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
314
315 /*
316 * Configure gpu_cc_cx_gmu_clk with recommended
317 * wakeup/sleep settings
318 */
319 mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT;
320 mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT;
321 value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT;
322 regmap_update_bits(regmap, 0x1098, mask, value);
323
324 return qcom_cc_really_probe(pdev, &gpu_cc_sm8250_desc, regmap);
325}
326
327static struct platform_driver gpu_cc_sm8250_driver = {
328 .probe = gpu_cc_sm8250_probe,
329 .driver = {
330 .name = "sm8250-gpucc",
331 .of_match_table = gpu_cc_sm8250_match_table,
332 },
333};
334
335static int __init gpu_cc_sm8250_init(void)
336{
337 return platform_driver_register(&gpu_cc_sm8250_driver);
338}
339subsys_initcall(gpu_cc_sm8250_init);
340
341static void __exit gpu_cc_sm8250_exit(void)
342{
343 platform_driver_unregister(&gpu_cc_sm8250_driver);
344}
345module_exit(gpu_cc_sm8250_exit);
346
347MODULE_DESCRIPTION("QTI GPU_CC SM8250 Driver");
348MODULE_LICENSE("GPL v2");
drivers/clk/qcom/lpasscorecc-sc7180.c+476−0
@@ -0,0 +1,476 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/err.h>
8#include <linux/module.h>
9#include <linux/of_device.h>
10#include <linux/pm_clock.h>
11#include <linux/pm_runtime.h>
12#include <linux/of.h>
13#include <linux/regmap.h>
14
15#include <dt-bindings/clock/qcom,lpasscorecc-sc7180.h>
16
17#include "clk-alpha-pll.h"
18#include "clk-branch.h"
19#include "clk-rcg.h"
20#include "clk-regmap.h"
21#include "common.h"
22#include "gdsc.h"
23
24enum {
25 P_BI_TCXO,
26 P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD,
27 P_SLEEP_CLK,
28};
29
30static struct pll_vco fabia_vco[] = {
31 { 249600000, 2000000000, 0 },
32};
33
34static const struct alpha_pll_config lpass_lpaaudio_dig_pll_config = {
35 .l = 0x20,
36 .alpha = 0x0,
37 .config_ctl_val = 0x20485699,
38 .config_ctl_hi_val = 0x00002067,
39 .test_ctl_val = 0x40000000,
40 .test_ctl_hi_val = 0x00000000,
41 .user_ctl_val = 0x00005105,
42 .user_ctl_hi_val = 0x00004805,
43};
44
45static const u8 clk_alpha_pll_regs_offset[][PLL_OFF_MAX_REGS] = {
46 [CLK_ALPHA_PLL_TYPE_FABIA] = {
47 [PLL_OFF_L_VAL] = 0x04,
48 [PLL_OFF_CAL_L_VAL] = 0x8,
49 [PLL_OFF_USER_CTL] = 0x0c,
50 [PLL_OFF_USER_CTL_U] = 0x10,
51 [PLL_OFF_USER_CTL_U1] = 0x14,
52 [PLL_OFF_CONFIG_CTL] = 0x18,
53 [PLL_OFF_CONFIG_CTL_U] = 0x1C,
54 [PLL_OFF_CONFIG_CTL_U1] = 0x20,
55 [PLL_OFF_TEST_CTL] = 0x24,
56 [PLL_OFF_TEST_CTL_U] = 0x28,
57 [PLL_OFF_STATUS] = 0x30,
58 [PLL_OFF_OPMODE] = 0x38,
59 [PLL_OFF_FRAC] = 0x40,
60 },
61};
62
63static struct clk_alpha_pll lpass_lpaaudio_dig_pll = {
64 .offset = 0x1000,
65 .vco_table = fabia_vco,
66 .num_vco = ARRAY_SIZE(fabia_vco),
67 .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_FABIA],
68 .clkr = {
69 .hw.init = &(struct clk_init_data){
70 .name = "lpass_lpaaudio_dig_pll",
71 .parent_data = &(const struct clk_parent_data){
72 .fw_name = "bi_tcxo",
73 },
74 .num_parents = 1,
75 .ops = &clk_alpha_pll_fabia_ops,
76 },
77 },
78};
79
80static const struct clk_div_table
81 post_div_table_lpass_lpaaudio_dig_pll_out_odd[] = {
82 { 0x5, 5 },
83 { }
84};
85
86static struct clk_alpha_pll_postdiv lpass_lpaaudio_dig_pll_out_odd = {
87 .offset = 0x1000,
88 .post_div_shift = 12,
89 .post_div_table = post_div_table_lpass_lpaaudio_dig_pll_out_odd,
90 .num_post_div =
91 ARRAY_SIZE(post_div_table_lpass_lpaaudio_dig_pll_out_odd),
92 .width = 4,
93 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
94 .clkr.hw.init = &(struct clk_init_data){
95 .name = "lpass_lpaaudio_dig_pll_out_odd",
96 .parent_data = &(const struct clk_parent_data){
97 .hw = &lpass_lpaaudio_dig_pll.clkr.hw,
98 },
99 .num_parents = 1,
100 .flags = CLK_SET_RATE_PARENT,
101 .ops = &clk_alpha_pll_postdiv_fabia_ops,
102 },
103};
104
105static const struct parent_map lpass_core_cc_parent_map_0[] = {
106 { P_BI_TCXO, 0 },
107 { P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 5 },
108};
109
110static const struct clk_parent_data lpass_core_cc_parent_data_0[] = {
111 { .fw_name = "bi_tcxo" },
112 { .hw = &lpass_lpaaudio_dig_pll_out_odd.clkr.hw },
113};
114
115static const struct parent_map lpass_core_cc_parent_map_2[] = {
116 { P_BI_TCXO, 0 },
117};
118
119static struct clk_rcg2 core_clk_src = {
120 .cmd_rcgr = 0x1d000,
121 .mnd_width = 8,
122 .hid_width = 5,
123 .parent_map = lpass_core_cc_parent_map_2,
124 .clkr.hw.init = &(struct clk_init_data){
125 .name = "core_clk_src",
126 .parent_data = &(const struct clk_parent_data){
127 .fw_name = "bi_tcxo",
128 },
129 .num_parents = 1,
130 .ops = &clk_rcg2_ops,
131 },
132};
133
134static const struct freq_tbl ftbl_ext_mclk0_clk_src[] = {
135 F(9600000, P_BI_TCXO, 2, 0, 0),
136 F(19200000, P_BI_TCXO, 1, 0, 0),
137 { }
138};
139
140static const struct freq_tbl ftbl_ext_lpaif_clk_src[] = {
141 F(256000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 32),
142 F(512000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 16),
143 F(768000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 16),
144 F(1024000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 8),
145 F(1536000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 8),
146 F(2048000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 4),
147 F(3072000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 4),
148 F(4096000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 2),
149 F(6144000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 2),
150 F(8192000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 0, 0),
151 F(9600000, P_BI_TCXO, 2, 0, 0),
152 F(12288000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 0, 0),
153 F(19200000, P_BI_TCXO, 1, 0, 0),
154 F(24576000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 5, 0, 0),
155 { }
156};
157
158static struct clk_rcg2 ext_mclk0_clk_src = {
159 .cmd_rcgr = 0x20000,
160 .mnd_width = 8,
161 .hid_width = 5,
162 .parent_map = lpass_core_cc_parent_map_0,
163 .freq_tbl = ftbl_ext_mclk0_clk_src,
164 .clkr.hw.init = &(struct clk_init_data){
165 .name = "ext_mclk0_clk_src",
166 .parent_data = lpass_core_cc_parent_data_0,
167 .num_parents = 2,
168 .flags = CLK_SET_RATE_PARENT,
169 .ops = &clk_rcg2_ops,
170 },
171};
172
173static struct clk_rcg2 lpaif_pri_clk_src = {
174 .cmd_rcgr = 0x10000,
175 .mnd_width = 16,
176 .hid_width = 5,
177 .parent_map = lpass_core_cc_parent_map_0,
178 .freq_tbl = ftbl_ext_lpaif_clk_src,
179 .clkr.hw.init = &(struct clk_init_data){
180 .name = "lpaif_pri_clk_src",
181 .parent_data = lpass_core_cc_parent_data_0,
182 .num_parents = 2,
183 .flags = CLK_SET_RATE_PARENT,
184 .ops = &clk_rcg2_ops,
185 },
186};
187
188static struct clk_rcg2 lpaif_sec_clk_src = {
189 .cmd_rcgr = 0x11000,
190 .mnd_width = 16,
191 .hid_width = 5,
192 .parent_map = lpass_core_cc_parent_map_0,
193 .freq_tbl = ftbl_ext_lpaif_clk_src,
194 .clkr.hw.init = &(struct clk_init_data){
195 .name = "lpaif_sec_clk_src",
196 .parent_data = lpass_core_cc_parent_data_0,
197 .num_parents = 2,
198 .flags = CLK_SET_RATE_PARENT,
199 .ops = &clk_rcg2_ops,
200 },
201};
202
203static struct clk_branch lpass_audio_core_ext_mclk0_clk = {
204 .halt_reg = 0x20014,
205 .halt_check = BRANCH_HALT,
206 .hwcg_reg = 0x20014,
207 .hwcg_bit = 1,
208 .clkr = {
209 .enable_reg = 0x20014,
210 .enable_mask = BIT(0),
211 .hw.init = &(struct clk_init_data){
212 .name = "lpass_audio_core_ext_mclk0_clk",
213 .parent_data = &(const struct clk_parent_data){
214 .hw = &ext_mclk0_clk_src.clkr.hw,
215 },
216 .num_parents = 1,
217 .flags = CLK_SET_RATE_PARENT,
218 .ops = &clk_branch2_ops,
219 },
220 },
221};
222
223static struct clk_branch lpass_audio_core_lpaif_pri_ibit_clk = {
224 .halt_reg = 0x10018,
225 .halt_check = BRANCH_HALT,
226 .hwcg_reg = 0x10018,
227 .hwcg_bit = 1,
228 .clkr = {
229 .enable_reg = 0x10018,
230 .enable_mask = BIT(0),
231 .hw.init = &(struct clk_init_data){
232 .name = "lpass_audio_core_lpaif_pri_ibit_clk",
233 .parent_data = &(const struct clk_parent_data){
234 .hw = &lpaif_pri_clk_src.clkr.hw,
235 },
236 .num_parents = 1,
237 .flags = CLK_SET_RATE_PARENT,
238 .ops = &clk_branch2_ops,
239 },
240 },
241};
242
243static struct clk_branch lpass_audio_core_lpaif_sec_ibit_clk = {
244 .halt_reg = 0x11018,
245 .halt_check = BRANCH_HALT,
246 .hwcg_reg = 0x11018,
247 .hwcg_bit = 1,
248 .clkr = {
249 .enable_reg = 0x11018,
250 .enable_mask = BIT(0),
251 .hw.init = &(struct clk_init_data){
252 .name = "lpass_audio_core_lpaif_sec_ibit_clk",
253 .parent_data = &(const struct clk_parent_data){
254 .hw = &lpaif_sec_clk_src.clkr.hw,
255 },
256 .num_parents = 1,
257 .flags = CLK_SET_RATE_PARENT,
258 .ops = &clk_branch2_ops,
259 },
260 },
261};
262
263static struct clk_branch lpass_audio_core_sysnoc_mport_core_clk = {
264 .halt_reg = 0x23000,
265 .halt_check = BRANCH_HALT,
266 .hwcg_reg = 0x23000,
267 .hwcg_bit = 1,
268 .clkr = {
269 .enable_reg = 0x23000,
270 .enable_mask = BIT(0),
271 .hw.init = &(struct clk_init_data){
272 .name = "lpass_audio_core_sysnoc_mport_core_clk",
273 .parent_data = &(const struct clk_parent_data){
274 .hw = &core_clk_src.clkr.hw,
275 },
276 .num_parents = 1,
277 .flags = CLK_SET_RATE_PARENT,
278 .ops = &clk_branch2_ops,
279 },
280 },
281};
282
283static struct clk_regmap *lpass_core_cc_sc7180_clocks[] = {
284 [EXT_MCLK0_CLK_SRC] = &ext_mclk0_clk_src.clkr,
285 [LPAIF_PRI_CLK_SRC] = &lpaif_pri_clk_src.clkr,
286 [LPAIF_SEC_CLK_SRC] = &lpaif_sec_clk_src.clkr,
287 [CORE_CLK_SRC] = &core_clk_src.clkr,
288 [LPASS_AUDIO_CORE_EXT_MCLK0_CLK] = &lpass_audio_core_ext_mclk0_clk.clkr,
289 [LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK] =
290 &lpass_audio_core_lpaif_pri_ibit_clk.clkr,
291 [LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK] =
292 &lpass_audio_core_lpaif_sec_ibit_clk.clkr,
293 [LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK] =
294 &lpass_audio_core_sysnoc_mport_core_clk.clkr,
295 [LPASS_LPAAUDIO_DIG_PLL] = &lpass_lpaaudio_dig_pll.clkr,
296 [LPASS_LPAAUDIO_DIG_PLL_OUT_ODD] = &lpass_lpaaudio_dig_pll_out_odd.clkr,
297};
298
299static struct gdsc lpass_pdc_hm_gdsc = {
300 .gdscr = 0x3090,
301 .pd = {
302 .name = "lpass_pdc_hm_gdsc",
303 },
304 .pwrsts = PWRSTS_OFF_ON,
305 .flags = VOTABLE,
306};
307
308static struct gdsc lpass_audio_hm_gdsc = {
309 .gdscr = 0x9090,
310 .pd = {
311 .name = "lpass_audio_hm_gdsc",
312 },
313 .pwrsts = PWRSTS_OFF_ON,
314};
315
316static struct gdsc lpass_core_hm_gdsc = {
317 .gdscr = 0x0,
318 .pd = {
319 .name = "lpass_core_hm_gdsc",
320 },
321 .pwrsts = PWRSTS_OFF_ON,
322 .flags = RETAIN_FF_ENABLE,
323};
324
325static struct gdsc *lpass_core_hm_sc7180_gdscs[] = {
326 [LPASS_CORE_HM_GDSCR] = &lpass_core_hm_gdsc,
327};
328
329static struct gdsc *lpass_audio_hm_sc7180_gdscs[] = {
330 [LPASS_PDC_HM_GDSCR] = &lpass_pdc_hm_gdsc,
331 [LPASS_AUDIO_HM_GDSCR] = &lpass_audio_hm_gdsc,
332};
333
334static struct regmap_config lpass_core_cc_sc7180_regmap_config = {
335 .reg_bits = 32,
336 .reg_stride = 4,
337 .val_bits = 32,
338 .fast_io = true,
339};
340
341static const struct qcom_cc_desc lpass_core_hm_sc7180_desc = {
342 .config = &lpass_core_cc_sc7180_regmap_config,
343 .gdscs = lpass_core_hm_sc7180_gdscs,
344 .num_gdscs = ARRAY_SIZE(lpass_core_hm_sc7180_gdscs),
345};
346
347static const struct qcom_cc_desc lpass_core_cc_sc7180_desc = {
348 .config = &lpass_core_cc_sc7180_regmap_config,
349 .clks = lpass_core_cc_sc7180_clocks,
350 .num_clks = ARRAY_SIZE(lpass_core_cc_sc7180_clocks),
351};
352
353static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = {
354 .config = &lpass_core_cc_sc7180_regmap_config,
355 .gdscs = lpass_audio_hm_sc7180_gdscs,
356 .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs),
357};
358
359static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
360{
361 const struct qcom_cc_desc *desc;
362 struct regmap *regmap;
363 int ret;
364
365 lpass_core_cc_sc7180_regmap_config.name = "lpass_audio_cc";
366 desc = &lpass_audio_hm_sc7180_desc;
367 ret = qcom_cc_probe_by_index(pdev, 1, desc);
368 if (ret)
369 return ret;
370
371 lpass_core_cc_sc7180_regmap_config.name = "lpass_core_cc";
372 regmap = qcom_cc_map(pdev, &lpass_core_cc_sc7180_desc);
373 if (IS_ERR(regmap))
374 return PTR_ERR(regmap);
375
376 /*
377 * Keep the CLK always-ON
378 * LPASS_AUDIO_CORE_SYSNOC_SWAY_CORE_CLK
379 */
380 regmap_update_bits(regmap, 0x24000, BIT(0), BIT(0));
381
382 /* PLL settings */
383 regmap_write(regmap, 0x1008, 0x20);
384 regmap_update_bits(regmap, 0x1014, BIT(0), BIT(0));
385
386 clk_fabia_pll_configure(&lpass_lpaaudio_dig_pll, regmap,
387 &lpass_lpaaudio_dig_pll_config);
388
389 return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap);
390}
391
392static int lpass_hm_core_probe(struct platform_device *pdev)
393{
394 const struct qcom_cc_desc *desc;
395
396 lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core";
397 desc = &lpass_core_hm_sc7180_desc;
398
399 return qcom_cc_probe_by_index(pdev, 0, desc);
400}
401
402static const struct of_device_id lpass_core_cc_sc7180_match_table[] = {
403 {
404 .compatible = "qcom,sc7180-lpasshm",
405 .data = lpass_hm_core_probe,
406 },
407 {
408 .compatible = "qcom,sc7180-lpasscorecc",
409 .data = lpass_core_cc_sc7180_probe,
410 },
411 { }
412};
413MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table);
414
415static int lpass_core_sc7180_probe(struct platform_device *pdev)
416{
417 int (*clk_probe)(struct platform_device *p);
418 int ret;
419
420 pm_runtime_enable(&pdev->dev);
421 ret = pm_clk_create(&pdev->dev);
422 if (ret)
423 return ret;
424
425 ret = pm_clk_add(&pdev->dev, "iface");
426 if (ret < 0) {
427 dev_err(&pdev->dev, "failed to acquire iface clock\n");
428 goto disable_pm_runtime;
429 }
430
431 clk_probe = of_device_get_match_data(&pdev->dev);
432 if (!clk_probe)
433 return -EINVAL;
434
435 ret = clk_probe(pdev);
436 if (ret)
437 goto destroy_pm_clk;
438
439 return 0;
440
441destroy_pm_clk:
442 pm_clk_destroy(&pdev->dev);
443
444disable_pm_runtime:
445 pm_runtime_disable(&pdev->dev);
446
447 return ret;
448}
449
450static const struct dev_pm_ops lpass_core_cc_pm_ops = {
451 SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
452};
453
454static struct platform_driver lpass_core_cc_sc7180_driver = {
455 .probe = lpass_core_sc7180_probe,
456 .driver = {
457 .name = "lpass_core_cc-sc7180",
458 .of_match_table = lpass_core_cc_sc7180_match_table,
459 .pm = &lpass_core_cc_pm_ops,
460 },
461};
462
463static int __init lpass_core_cc_sc7180_init(void)
464{
465 return platform_driver_register(&lpass_core_cc_sc7180_driver);
466}
467subsys_initcall(lpass_core_cc_sc7180_init);
468
469static void __exit lpass_core_cc_sc7180_exit(void)
470{
471 platform_driver_unregister(&lpass_core_cc_sc7180_driver);
472}
473module_exit(lpass_core_cc_sc7180_exit);
474
475MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7180 Driver");
476MODULE_LICENSE("GPL v2");
drivers/clk/rockchip/clk-pll.c+41−29
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include <linux/io.h>12#include <linux/io.h>
13#include <linux/delay.h>13#include <linux/delay.h>
14#include <linux/clk-provider.h>14#include <linux/clk-provider.h>
15#include <linux/iopoll.h>
15#include <linux/regmap.h>16#include <linux/regmap.h>
16#include <linux/clk.h>17#include <linux/clk.h>
17#include "clk.h"18#include "clk.h"
@@ -86,23 +87,14 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) · 68 unmodified lines
86{87{
87 struct regmap *grf = pll->ctx->grf;88 struct regmap *grf = pll->ctx->grf;
88 unsigned int val;89 unsigned int val;
89 int delay = 24000000, ret;90 int ret;
90
91 while (delay > 0) {
92 ret = regmap_read(grf, pll->lock_offset, &val);
93 if (ret) {
94 pr_err("%s: failed to read pll lock status: %d\n",
95 __func__, ret);
96 return ret;
97 }
98 91
99 if (val & BIT(pll->lock_shift))92 ret = regmap_read_poll_timeout(grf, pll->lock_offset, val,
100 return 0;93 val & BIT(pll->lock_shift), 0, 1000);
101 delay--;94 if (ret)
102 }95 pr_err("%s: timeout waiting for pll to lock\n", __func__);
103 96
104 pr_err("%s: timeout waiting for pll to lock\n", __func__);97 return ret;
105 return -ETIMEDOUT;
106}98}
107 99
108/**100/**
@@ -118,12 +110,31 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) · 9 unmodified lines
118#define RK3036_PLLCON1_REFDIV_SHIFT 0110#define RK3036_PLLCON1_REFDIV_SHIFT 0
119#define RK3036_PLLCON1_POSTDIV2_MASK 0x7111#define RK3036_PLLCON1_POSTDIV2_MASK 0x7
120#define RK3036_PLLCON1_POSTDIV2_SHIFT 6112#define RK3036_PLLCON1_POSTDIV2_SHIFT 6
113#define RK3036_PLLCON1_LOCK_STATUS BIT(10)
121#define RK3036_PLLCON1_DSMPD_MASK 0x1114#define RK3036_PLLCON1_DSMPD_MASK 0x1
122#define RK3036_PLLCON1_DSMPD_SHIFT 12115#define RK3036_PLLCON1_DSMPD_SHIFT 12
116#define RK3036_PLLCON1_PWRDOWN BIT(13)
123#define RK3036_PLLCON2_FRAC_MASK 0xffffff117#define RK3036_PLLCON2_FRAC_MASK 0xffffff
124#define RK3036_PLLCON2_FRAC_SHIFT 0118#define RK3036_PLLCON2_FRAC_SHIFT 0
125 119
126#define RK3036_PLLCON1_PWRDOWN (1 << 13)120static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll)
121{
122 u32 pllcon;
123 int ret;
124
125 /*
126 * Lock time typical 250, max 500 input clock cycles @24MHz
127 * So define a very safe maximum of 1000us, meaning 24000 cycles.
128 */
129 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1),
130 pllcon,
131 pllcon & RK3036_PLLCON1_LOCK_STATUS,
132 0, 1000);
133 if (ret)
134 pr_err("%s: timeout waiting for pll to lock\n", __func__);
135
136 return ret;
137}
127 138
128static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,139static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,
129 struct rockchip_pll_rate_table *rate)140 struct rockchip_pll_rate_table *rate)
@@ -221,7 +232,7 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, · 91 unmodified lines
221 writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));232 writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
222 233
223 /* wait for the pll to lock */234 /* wait for the pll to lock */
224 ret = rockchip_pll_wait_lock(pll);235 ret = rockchip_rk3036_pll_wait_lock(pll);
225 if (ret) {236 if (ret) {
226 pr_warn("%s: pll update unsuccessful, trying to restore old params\n",237 pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
227 __func__);238 __func__);
@@ -260,7 +271,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) · 32 unmodified lines
260 271
261 writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),272 writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
262 pll->reg_base + RK3036_PLLCON(1));273 pll->reg_base + RK3036_PLLCON(1));
263 rockchip_pll_wait_lock(pll);274 rockchip_rk3036_pll_wait_lock(pll);
264 275
265 return 0;276 return 0;
266}277}
@@ -589,19 +600,20 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { · 322 unmodified lines
589static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)600static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)
590{601{
591 u32 pllcon;602 u32 pllcon;
592 int delay = 24000000;603 int ret;
593
594 /* poll check the lock status in rk3399 xPLLCON2 */
595 while (delay > 0) {
596 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
597 if (pllcon & RK3399_PLLCON2_LOCK_STATUS)
598 return 0;
599 604
600 delay--;605 /*
601 }606 * Lock time typical 250, max 500 input clock cycles @24MHz
607 * So define a very safe maximum of 1000us, meaning 24000 cycles.
608 */
609 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2),
610 pllcon,
611 pllcon & RK3399_PLLCON2_LOCK_STATUS,
612 0, 1000);
613 if (ret)
614 pr_err("%s: timeout waiting for pll to lock\n", __func__);
602 615
603 pr_err("%s: timeout waiting for pll to lock\n", __func__);616 return ret;
604 return -ETIMEDOUT;
605}617}
606 618
607static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,619static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,
drivers/clk/rockchip/clk-rk3188.c+1−0
@@ -751,6 +751,7 @@ static const char *const rk3188_critical_clocks[] __initconst = { · 750 unmodified lines
751 "pclk_peri",751 "pclk_peri",
752 "hclk_cpubus",752 "hclk_cpubus",
753 "hclk_vio_bus",753 "hclk_vio_bus",
754 "sclk_mac_lbtest",
754};755};
755 756
756static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np)757static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np)
drivers/clk/rockchip/clk-rk3288.c+36−3
@@ -15,6 +15,11 @@ · 14 unmodified lines
15#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)15#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)
16#define RK3288_GRF_SOC_STATUS1 0x28416#define RK3288_GRF_SOC_STATUS1 0x284
17 17
18enum rk3288_variant {
19 RK3288_CRU,
20 RK3288W_CRU,
21};
22
18enum rk3288_plls {23enum rk3288_plls {
19 apll, dpll, cpll, gpll, npll,24 apll, dpll, cpll, gpll, npll,
20};25};
@@ -425,8 +430,6 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { · 404 unmodified lines
425 COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,430 COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
426 RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,431 RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
427 RK3288_CLKGATE_CON(3), 0, GFLAGS),432 RK3288_CLKGATE_CON(3), 0, GFLAGS),
428 DIV(0, "hclk_vio", "aclk_vio0", 0,
429 RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
430 COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,433 COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
431 RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,434 RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
432 RK3288_CLKGATE_CON(3), 2, GFLAGS),435 RK3288_CLKGATE_CON(3), 2, GFLAGS),
@@ -819,6 +822,16 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { · 386 unmodified lines
819 INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),822 INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
820};823};
821 824
825static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = {
826 DIV(0, "hclk_vio", "aclk_vio1", 0,
827 RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
828};
829
830static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = {
831 DIV(0, "hclk_vio", "aclk_vio0", 0,
832 RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
833};
834
822static const char *const rk3288_critical_clocks[] __initconst = {835static const char *const rk3288_critical_clocks[] __initconst = {
823 "aclk_cpu",836 "aclk_cpu",
824 "aclk_peri",837 "aclk_peri",
@@ -914,7 +927,8 @@ static struct syscore_ops rk3288_clk_syscore_ops = { · 89 unmodified lines
914 .resume = rk3288_clk_resume,927 .resume = rk3288_clk_resume,
915};928};
916 929
917static void __init rk3288_clk_init(struct device_node *np)930static void __init rk3288_common_init(struct device_node *np,
931 enum rk3288_variant soc)
918{932{
919 struct rockchip_clk_provider *ctx;933 struct rockchip_clk_provider *ctx;
920 934
@@ -936,6 +950,14 @@ static void __init rk3288_clk_init(struct device_node *np) · 15 unmodified lines
936 RK3288_GRF_SOC_STATUS1);950 RK3288_GRF_SOC_STATUS1);
937 rockchip_clk_register_branches(ctx, rk3288_clk_branches,951 rockchip_clk_register_branches(ctx, rk3288_clk_branches,
938 ARRAY_SIZE(rk3288_clk_branches));952 ARRAY_SIZE(rk3288_clk_branches));
953
954 if (soc == RK3288W_CRU)
955 rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch,
956 ARRAY_SIZE(rk3288w_hclkvio_branch));
957 else
958 rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch,
959 ARRAY_SIZE(rk3288_hclkvio_branch));
960
939 rockchip_clk_protect_critical(rk3288_critical_clocks,961 rockchip_clk_protect_critical(rk3288_critical_clocks,
940 ARRAY_SIZE(rk3288_critical_clocks));962 ARRAY_SIZE(rk3288_critical_clocks));
941 963
@@ -954,4 +976,15 @@ static void __init rk3288_clk_init(struct device_node *np) · 12 unmodified lines
954 976
955 rockchip_clk_of_add_provider(np, ctx);977 rockchip_clk_of_add_provider(np, ctx);
956}978}
979
980static void __init rk3288_clk_init(struct device_node *np)
981{
982 rk3288_common_init(np, RK3288_CRU);
983}
957CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);984CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
985
986static void __init rk3288w_clk_init(struct device_node *np)
987{
988 rk3288_common_init(np, RK3288W_CRU);
989}
990CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init);
drivers/clk/rockchip/clk-rk3328.c+4−4
@@ -808,22 +808,22 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { · 807 unmodified lines
808 MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc",808 MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc",
809 RK3328_SDMMC_CON0, 1),809 RK3328_SDMMC_CON0, 1),
810 MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc",810 MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc",
811 RK3328_SDMMC_CON1, 0),811 RK3328_SDMMC_CON1, 1),
812 812
813 MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio",813 MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio",
814 RK3328_SDIO_CON0, 1),814 RK3328_SDIO_CON0, 1),
815 MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio",815 MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio",
816 RK3328_SDIO_CON1, 0),816 RK3328_SDIO_CON1, 1),
817 817
818 MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc",818 MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc",
819 RK3328_EMMC_CON0, 1),819 RK3328_EMMC_CON0, 1),
820 MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc",820 MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc",
821 RK3328_EMMC_CON1, 0),821 RK3328_EMMC_CON1, 1),
822 822
823 MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext",823 MMC(SCLK_SDMMC_EXT_DRV, "sdmmc_ext_drv", "clk_sdmmc_ext",
824 RK3328_SDMMC_EXT_CON0, 1),824 RK3328_SDMMC_EXT_CON0, 1),
825 MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext",825 MMC(SCLK_SDMMC_EXT_SAMPLE, "sdmmc_ext_sample", "clk_sdmmc_ext",
826 RK3328_SDMMC_EXT_CON1, 0),826 RK3328_SDMMC_EXT_CON1, 1),
827};827};
828 828
829static const char *const rk3328_critical_clocks[] __initconst = {829static const char *const rk3328_critical_clocks[] __initconst = {
drivers/clk/sirf/clk-atlas6.c+1−1
@@ -135,7 +135,7 @@ static void __init atlas6_clk_init(struct device_node *np) · 134 unmodified lines
135 135
136 for (i = pll1; i < maxclk; i++) {136 for (i = pll1; i < maxclk; i++) {
137 atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]);137 atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]);
138 BUG_ON(!atlas6_clks[i]);138 BUG_ON(IS_ERR(atlas6_clks[i]));
139 }139 }
140 clk_register_clkdev(atlas6_clks[cpu], NULL, "cpu");140 clk_register_clkdev(atlas6_clks[cpu], NULL, "cpu");
141 clk_register_clkdev(atlas6_clks[io], NULL, "io");141 clk_register_clkdev(atlas6_clks[io], NULL, "io");
drivers/clk/tegra/clk-pll.c+15−5
@@ -327,16 +327,26 @@ int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll) · 326 unmodified lines
327 return clk_pll_wait_for_lock(pll);327 return clk_pll_wait_for_lock(pll);
328}328}
329 329
330static bool pllm_clk_is_gated_by_pmc(struct tegra_clk_pll *pll)
331{
332 u32 val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
333
334 return (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) &&
335 !(val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE);
336}
337
330static int clk_pll_is_enabled(struct clk_hw *hw)338static int clk_pll_is_enabled(struct clk_hw *hw)
331{339{
332 struct tegra_clk_pll *pll = to_clk_pll(hw);340 struct tegra_clk_pll *pll = to_clk_pll(hw);
333 u32 val;341 u32 val;
334 342
335 if (pll->params->flags & TEGRA_PLLM) {343 /*
336 val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);344 * Power Management Controller (PMC) can override the PLLM clock
337 if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)345 * settings, including the enable-state. The PLLM is enabled when
338 return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;346 * PLLM's CaR state is ON and when PLLM isn't gated by PMC.
339 }347 */
348 if ((pll->params->flags & TEGRA_PLLM) && pllm_clk_is_gated_by_pmc(pll))
349 return 0;
340 350
341 val = pll_readl_base(pll);351 val = pll_readl_base(pll);
342 352
drivers/clk/x86/clk-cgu-pll.c+1−1
@@ -128,7 +128,7 @@ lgm_clk_register_pll(struct lgm_clk_provider *ctx, · 127 unmodified lines
128 pll->hw.init = &init;128 pll->hw.init = &init;
129 129
130 hw = &pll->hw;130 hw = &pll->hw;
131 ret = clk_hw_register(dev, hw);131 ret = devm_clk_hw_register(dev, hw);
132 if (ret)132 if (ret)
133 return ERR_PTR(ret);133 return ERR_PTR(ret);
134 134
drivers/clk/x86/clk-cgu.c+12−20
@@ -119,7 +119,7 @@ lgm_clk_register_mux(struct lgm_clk_provider *ctx, · 118 unmodified lines
119 mux->hw.init = &init;119 mux->hw.init = &init;
120 120
121 hw = &mux->hw;121 hw = &mux->hw;
122 ret = clk_hw_register(dev, hw);122 ret = devm_clk_hw_register(dev, hw);
123 if (ret)123 if (ret)
124 return ERR_PTR(ret);124 return ERR_PTR(ret);
125 125
@@ -247,7 +247,7 @@ lgm_clk_register_divider(struct lgm_clk_provider *ctx, · 121 unmodified lines
247 div->hw.init = &init;247 div->hw.init = &init;
248 248
249 hw = &div->hw;249 hw = &div->hw;
250 ret = clk_hw_register(dev, hw);250 ret = devm_clk_hw_register(dev, hw);
251 if (ret)251 if (ret)
252 return ERR_PTR(ret);252 return ERR_PTR(ret);
253 253
@@ -361,7 +361,7 @@ lgm_clk_register_gate(struct lgm_clk_provider *ctx, · 107 unmodified lines
361 gate->hw.init = &init;361 gate->hw.init = &init;
362 362
363 hw = &gate->hw;363 hw = &gate->hw;
364 ret = clk_hw_register(dev, hw);364 ret = devm_clk_hw_register(dev, hw);
365 if (ret)365 if (ret)
366 return ERR_PTR(ret);366 return ERR_PTR(ret);
367 367
@@ -420,18 +420,14 @@ lgm_clk_ddiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) · 52 unmodified lines
420{420{
421 struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);421 struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
422 unsigned int div0, div1, exdiv;422 unsigned int div0, div1, exdiv;
423 unsigned long flags;
424 u64 prate;423 u64 prate;
425 424
426 spin_lock_irqsave(&ddiv->lock, flags);
427 div0 = lgm_get_clk_val(ddiv->membase, ddiv->reg,425 div0 = lgm_get_clk_val(ddiv->membase, ddiv->reg,
428 ddiv->shift0, ddiv->width0) + 1;426 ddiv->shift0, ddiv->width0) + 1;
429 div1 = lgm_get_clk_val(ddiv->membase, ddiv->reg,427 div1 = lgm_get_clk_val(ddiv->membase, ddiv->reg,
430 ddiv->shift1, ddiv->width1) + 1;428 ddiv->shift1, ddiv->width1) + 1;
431 exdiv = lgm_get_clk_val(ddiv->membase, ddiv->reg,429 exdiv = lgm_get_clk_val(ddiv->membase, ddiv->reg,
432 ddiv->shift2, ddiv->width2);430 ddiv->shift2, ddiv->width2);
433 spin_unlock_irqrestore(&ddiv->lock, flags);
434
435 prate = (u64)parent_rate;431 prate = (u64)parent_rate;
436 do_div(prate, div0);432 do_div(prate, div0);
437 do_div(prate, div1);433 do_div(prate, div1);
@@ -548,24 +544,21 @@ lgm_clk_ddiv_round_rate(struct clk_hw *hw, unsigned long rate, · 110 unmodified lines
548 div = div * 2;544 div = div * 2;
549 div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);545 div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);
550 }546 }
547 spin_unlock_irqrestore(&ddiv->lock, flags);
551 548
552 if (div <= 0) {549 if (div <= 0)
553 spin_unlock_irqrestore(&ddiv->lock, flags);
554 return *prate;550 return *prate;
555 }
556 551
557 if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2) != 0) {552 if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2) != 0)
558 if (lgm_clk_get_ddiv_val(div + 1, &ddiv1, &ddiv2) != 0) {553 if (lgm_clk_get_ddiv_val(div + 1, &ddiv1, &ddiv2) != 0)
559 spin_unlock_irqrestore(&ddiv->lock, flags);
560 return -EINVAL;554 return -EINVAL;
561 }
562 }
563 555
564 rate64 = *prate;556 rate64 = *prate;
565 do_div(rate64, ddiv1);557 do_div(rate64, ddiv1);
566 do_div(rate64, ddiv2);558 do_div(rate64, ddiv2);
567 559
568 /* if predivide bit is enabled, modify rounded rate by factor of 2.5 */560 /* if predivide bit is enabled, modify rounded rate by factor of 2.5 */
561 spin_lock_irqsave(&ddiv->lock, flags);
569 if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {562 if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
570 rate64 = rate64 * 2;563 rate64 = rate64 * 2;
571 rate64 = DIV_ROUND_CLOSEST_ULL(rate64, 5);564 rate64 = DIV_ROUND_CLOSEST_ULL(rate64, 5);
@@ -588,19 +581,18 @@ int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx, · 16 unmodified lines
588 unsigned int nr_clk)581 unsigned int nr_clk)
589{582{
590 struct device *dev = ctx->dev;583 struct device *dev = ctx->dev;
591 struct clk_init_data init = {};
592 struct lgm_clk_ddiv *ddiv;
593 struct clk_hw *hw;584 struct clk_hw *hw;
594 unsigned int idx;585 unsigned int idx;
595 int ret;586 int ret;
596 587
597 for (idx = 0; idx < nr_clk; idx++, list++) {588 for (idx = 0; idx < nr_clk; idx++, list++) {
598 ddiv = NULL;589 struct clk_init_data init = {};
590 struct lgm_clk_ddiv *ddiv;
591
599 ddiv = devm_kzalloc(dev, sizeof(*ddiv), GFP_KERNEL);592 ddiv = devm_kzalloc(dev, sizeof(*ddiv), GFP_KERNEL);
600 if (!ddiv)593 if (!ddiv)
601 return -ENOMEM;594 return -ENOMEM;
602 595
603 memset(&init, 0, sizeof(init));
604 init.name = list->name;596 init.name = list->name;
605 init.ops = &lgm_clk_ddiv_ops;597 init.ops = &lgm_clk_ddiv_ops;
606 init.flags = list->flags;598 init.flags = list->flags;
@@ -624,7 +616,7 @@ int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx, · 17 unmodified lines
624 ddiv->hw.init = &init;616 ddiv->hw.init = &init;
625 617
626 hw = &ddiv->hw;618 hw = &ddiv->hw;
627 ret = clk_hw_register(dev, hw);619 ret = devm_clk_hw_register(dev, hw);
628 if (ret) {620 if (ret) {
629 dev_err(dev, "register clk: %s failed!\n", list->name);621 dev_err(dev, "register clk: %s failed!\n", list->name);
630 return ret;622 return ret;
include/dt-bindings/clock/actions,s500-cmu.h+6−1
@@ -72,7 +72,12 @@ · 71 unmodified lines
72#define CLK_NAND 5272#define CLK_NAND 52
73#define CLK_ECC 5373#define CLK_ECC 53
74#define CLK_RMII_REF 5474#define CLK_RMII_REF 54
75#define CLK_GPIO 55
75 76
76#define CLK_NR_CLKS (CLK_RMII_REF + 1)77/* system clock (part 2) */
78#define CLK_APB 56
79#define CLK_DMAC 57
80
81#define CLK_NR_CLKS (CLK_DMAC + 1)
77 82
78#endif /* __DT_BINDINGS_CLOCK_S500_CMU_H */83#endif /* __DT_BINDINGS_CLOCK_S500_CMU_H */
include/dt-bindings/clock/jz4780-cgu.h+73−71
@@ -12,78 +12,80 @@ · 11 unmodified lines
12#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__12#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
13#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__13#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
14 14
15#define JZ4780_CLK_EXCLK 015#define JZ4780_CLK_EXCLK 0
16#define JZ4780_CLK_RTCLK 116#define JZ4780_CLK_RTCLK 1
17#define JZ4780_CLK_APLL 217#define JZ4780_CLK_APLL 2
18#define JZ4780_CLK_MPLL 318#define JZ4780_CLK_MPLL 3
19#define JZ4780_CLK_EPLL 419#define JZ4780_CLK_EPLL 4
20#define JZ4780_CLK_VPLL 520#define JZ4780_CLK_VPLL 5
21#define JZ4780_CLK_OTGPHY 621#define JZ4780_CLK_OTGPHY 6
22#define JZ4780_CLK_SCLKA 722#define JZ4780_CLK_SCLKA 7
23#define JZ4780_CLK_CPUMUX 823#define JZ4780_CLK_CPUMUX 8
24#define JZ4780_CLK_CPU 924#define JZ4780_CLK_CPU 9
25#define JZ4780_CLK_L2CACHE 1025#define JZ4780_CLK_L2CACHE 10
26#define JZ4780_CLK_AHB0 1126#define JZ4780_CLK_AHB0 11
27#define JZ4780_CLK_AHB2PMUX 1227#define JZ4780_CLK_AHB2PMUX 12
28#define JZ4780_CLK_AHB2 1328#define JZ4780_CLK_AHB2 13
29#define JZ4780_CLK_PCLK 1429#define JZ4780_CLK_PCLK 14
30#define JZ4780_CLK_DDR 1530#define JZ4780_CLK_DDR 15
31#define JZ4780_CLK_VPU 1631#define JZ4780_CLK_VPU 16
32#define JZ4780_CLK_I2SPLL 1732#define JZ4780_CLK_I2SPLL 17
33#define JZ4780_CLK_I2S 1833#define JZ4780_CLK_I2S 18
34#define JZ4780_CLK_LCD0PIXCLK 1934#define JZ4780_CLK_LCD0PIXCLK 19
35#define JZ4780_CLK_LCD1PIXCLK 2035#define JZ4780_CLK_LCD1PIXCLK 20
36#define JZ4780_CLK_MSCMUX 2136#define JZ4780_CLK_MSCMUX 21
37#define JZ4780_CLK_MSC0 2237#define JZ4780_CLK_MSC0 22
38#define JZ4780_CLK_MSC1 2338#define JZ4780_CLK_MSC1 23
39#define JZ4780_CLK_MSC2 2439#define JZ4780_CLK_MSC2 24
40#define JZ4780_CLK_UHC 2540#define JZ4780_CLK_UHC 25
41#define JZ4780_CLK_SSIPLL 2641#define JZ4780_CLK_SSIPLL 26
42#define JZ4780_CLK_SSI 2742#define JZ4780_CLK_SSI 27
43#define JZ4780_CLK_CIMMCLK 2843#define JZ4780_CLK_CIMMCLK 28
44#define JZ4780_CLK_PCMPLL 2944#define JZ4780_CLK_PCMPLL 29
45#define JZ4780_CLK_PCM 3045#define JZ4780_CLK_PCM 30
46#define JZ4780_CLK_GPU 3146#define JZ4780_CLK_GPU 31
47#define JZ4780_CLK_HDMI 3247#define JZ4780_CLK_HDMI 32
48#define JZ4780_CLK_BCH 3348#define JZ4780_CLK_BCH 33
49#define JZ4780_CLK_NEMC 3449#define JZ4780_CLK_NEMC 34
50#define JZ4780_CLK_OTG0 3550#define JZ4780_CLK_OTG0 35
51#define JZ4780_CLK_SSI0 3651#define JZ4780_CLK_SSI0 36
52#define JZ4780_CLK_SMB0 3752#define JZ4780_CLK_SMB0 37
53#define JZ4780_CLK_SMB1 3853#define JZ4780_CLK_SMB1 38
54#define JZ4780_CLK_SCC 3954#define JZ4780_CLK_SCC 39
55#define JZ4780_CLK_AIC 4055#define JZ4780_CLK_AIC 40
56#define JZ4780_CLK_TSSI0 4156#define JZ4780_CLK_TSSI0 41
57#define JZ4780_CLK_OWI 4257#define JZ4780_CLK_OWI 42
58#define JZ4780_CLK_KBC 4358#define JZ4780_CLK_KBC 43
59#define JZ4780_CLK_SADC 4459#define JZ4780_CLK_SADC 44
60#define JZ4780_CLK_UART0 4560#define JZ4780_CLK_UART0 45
61#define JZ4780_CLK_UART1 4661#define JZ4780_CLK_UART1 46
62#define JZ4780_CLK_UART2 4762#define JZ4780_CLK_UART2 47
63#define JZ4780_CLK_UART3 4863#define JZ4780_CLK_UART3 48
64#define JZ4780_CLK_SSI1 4964#define JZ4780_CLK_SSI1 49
65#define JZ4780_CLK_SSI2 5065#define JZ4780_CLK_SSI2 50
66#define JZ4780_CLK_PDMA 5166#define JZ4780_CLK_PDMA 51
67#define JZ4780_CLK_GPS 5267#define JZ4780_CLK_GPS 52
68#define JZ4780_CLK_MAC 5368#define JZ4780_CLK_MAC 53
69#define JZ4780_CLK_SMB2 5469#define JZ4780_CLK_SMB2 54
70#define JZ4780_CLK_CIM 5570#define JZ4780_CLK_CIM 55
71#define JZ4780_CLK_LCD 5671#define JZ4780_CLK_LCD 56
72#define JZ4780_CLK_TVE 5772#define JZ4780_CLK_TVE 57
73#define JZ4780_CLK_IPU 5873#define JZ4780_CLK_IPU 58
74#define JZ4780_CLK_DDR0 5974#define JZ4780_CLK_DDR0 59
75#define JZ4780_CLK_DDR1 6075#define JZ4780_CLK_DDR1 60
76#define JZ4780_CLK_SMB3 6176#define JZ4780_CLK_SMB3 61
77#define JZ4780_CLK_TSSI1 6277#define JZ4780_CLK_TSSI1 62
78#define JZ4780_CLK_COMPRESS 6378#define JZ4780_CLK_COMPRESS 63
79#define JZ4780_CLK_AIC1 6479#define JZ4780_CLK_AIC1 64
80#define JZ4780_CLK_GPVLC 6580#define JZ4780_CLK_GPVLC 65
81#define JZ4780_CLK_OTG1 6681#define JZ4780_CLK_OTG1 66
82#define JZ4780_CLK_UART4 6782#define JZ4780_CLK_UART4 67
83#define JZ4780_CLK_AHBMON 6883#define JZ4780_CLK_AHBMON 68
84#define JZ4780_CLK_SMB4 6984#define JZ4780_CLK_SMB4 69
85#define JZ4780_CLK_DES 7085#define JZ4780_CLK_DES 70
86#define JZ4780_CLK_X2D 7186#define JZ4780_CLK_X2D 71
87#define JZ4780_CLK_CORE1 7287#define JZ4780_CLK_CORE1 72
88#define JZ4780_CLK_EXCLK_DIV512 73
89#define JZ4780_CLK_RTC 74
88 90
89#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */91#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
include/dt-bindings/clock/qcom,gcc-sc7180.h+1−0
@@ -138,6 +138,7 @@ · 137 unmodified lines
138#define GCC_MSS_Q6_MEMNOC_AXI_CLK 128138#define GCC_MSS_Q6_MEMNOC_AXI_CLK 128
139#define GCC_MSS_SNOC_AXI_CLK 129139#define GCC_MSS_SNOC_AXI_CLK 129
140#define GCC_SEC_CTRL_CLK_SRC 130140#define GCC_SEC_CTRL_CLK_SRC 130
141#define GCC_LPASS_CFG_NOC_SWAY_CLK 131
141 142
142/* GCC resets */143/* GCC resets */
143#define GCC_QUSB2PHY_PRIM_BCR 0144#define GCC_QUSB2PHY_PRIM_BCR 0
include/dt-bindings/clock/qcom,gcc-sdm660.h+1−0
@@ -152,5 +152,6 @@ · 151 unmodified lines
152#define GCC_USB_20_BCR 6152#define GCC_USB_20_BCR 6
153#define GCC_USB_30_BCR 7153#define GCC_USB_30_BCR 7
154#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8154#define GCC_USB_PHY_CFG_AHB2PHY_BCR 8
155#define GCC_MSS_RESTART 9
155 156
156#endif157#endif
include/dt-bindings/clock/qcom,gpucc-sm8150.h+33−0
@@ -0,0 +1,33 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
4 */
5
6#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8150_H
7#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8150_H
8
9/* GPU_CC clock registers */
10#define GPU_CC_AHB_CLK 0
11#define GPU_CC_CRC_AHB_CLK 1
12#define GPU_CC_CX_APB_CLK 2
13#define GPU_CC_CX_GMU_CLK 3
14#define GPU_CC_CX_SNOC_DVM_CLK 4
15#define GPU_CC_CXO_AON_CLK 5
16#define GPU_CC_CXO_CLK 6
17#define GPU_CC_GMU_CLK_SRC 7
18#define GPU_CC_GX_GMU_CLK 8
19#define GPU_CC_PLL1 9
20
21/* GPU_CC Resets */
22#define GPUCC_GPU_CC_CX_BCR 0
23#define GPUCC_GPU_CC_GFX3D_AON_BCR 1
24#define GPUCC_GPU_CC_GMU_BCR 2
25#define GPUCC_GPU_CC_GX_BCR 3
26#define GPUCC_GPU_CC_SPDM_BCR 4
27#define GPUCC_GPU_CC_XO_BCR 5
28
29/* GPU_CC GDSCRs */
30#define GPU_CX_GDSC 0
31#define GPU_GX_GDSC 1
32
33#endif
include/dt-bindings/clock/qcom,gpucc-sm8250.h+34−0
@@ -0,0 +1,34 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
4 */
5
6#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8250_H
7#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8250_H
8
9/* GPU_CC clock registers */
10#define GPU_CC_AHB_CLK 0
11#define GPU_CC_CRC_AHB_CLK 1
12#define GPU_CC_CX_APB_CLK 2
13#define GPU_CC_CX_GMU_CLK 3
14#define GPU_CC_CX_SNOC_DVM_CLK 4
15#define GPU_CC_CXO_AON_CLK 5
16#define GPU_CC_CXO_CLK 6
17#define GPU_CC_GMU_CLK_SRC 7
18#define GPU_CC_GX_GMU_CLK 8
19#define GPU_CC_PLL1 9
20#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 10
21
22/* GPU_CC Resets */
23#define GPUCC_GPU_CC_ACD_BCR 0
24#define GPUCC_GPU_CC_CX_BCR 1
25#define GPUCC_GPU_CC_GFX3D_AON_BCR 2
26#define GPUCC_GPU_CC_GMU_BCR 3
27#define GPUCC_GPU_CC_GX_BCR 4
28#define GPUCC_GPU_CC_XO_BCR 5
29
30/* GPU_CC GDSCRs */
31#define GPU_CX_GDSC 0
32#define GPU_GX_GDSC 1
33
34#endif
include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h+29−0
@@ -0,0 +1,29 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 */
5
6#ifndef _DT_BINDINGS_CLK_QCOM_LPASS_CORE_CC_SC7180_H
7#define _DT_BINDINGS_CLK_QCOM_LPASS_CORE_CC_SC7180_H
8
9/* LPASS_CORE_CC clocks */
10#define LPASS_LPAAUDIO_DIG_PLL 0
11#define LPASS_LPAAUDIO_DIG_PLL_OUT_ODD 1
12#define CORE_CLK_SRC 2
13#define EXT_MCLK0_CLK_SRC 3
14#define LPAIF_PRI_CLK_SRC 4
15#define LPAIF_SEC_CLK_SRC 5
16#define LPASS_AUDIO_CORE_CORE_CLK 6
17#define LPASS_AUDIO_CORE_EXT_MCLK0_CLK 7
18#define LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK 8
19#define LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK 9
20#define LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK 10
21
22/* LPASS Core power domains */
23#define LPASS_CORE_HM_GDSCR 0
24
25/* LPASS Audio power domains */
26#define LPASS_AUDIO_HM_GDSCR 0
27#define LPASS_PDC_HM_GDSCR 1
28
29#endif
include/dt-bindings/clock/x1000-cgu.h+2−0
@@ -48,5 +48,7 @@ · 47 unmodified lines
48#define X1000_CLK_SSI 3348#define X1000_CLK_SSI 33
49#define X1000_CLK_OST 3449#define X1000_CLK_OST 34
50#define X1000_CLK_PDMA 3550#define X1000_CLK_PDMA 35
51#define X1000_CLK_EXCLK_DIV512 36
52#define X1000_CLK_RTC 37
51 53
52#endif /* __DT_BINDINGS_CLOCK_X1000_CGU_H__ */54#endif /* __DT_BINDINGS_CLOCK_X1000_CGU_H__ */
include/dt-bindings/clock/x1830-cgu.h+2−0
@@ -51,5 +51,7 @@ · 50 unmodified lines
51#define X1830_CLK_TCU 3651#define X1830_CLK_TCU 36
52#define X1830_CLK_DTRNG 3752#define X1830_CLK_DTRNG 37
53#define X1830_CLK_OST 3853#define X1830_CLK_OST 38
54#define X1830_CLK_EXCLK_DIV512 39
55#define X1830_CLK_RTC 40
54 56
55#endif /* __DT_BINDINGS_CLOCK_X1830_CGU_H__ */57#endif /* __DT_BINDINGS_CLOCK_X1830_CGU_H__ */
include/dt-bindings/reset/actions,s500-reset.h+67−0
@@ -0,0 +1,67 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Device Tree binding constants for Actions Semi S500 Reset Management Unit
4 *
5 * Copyright (c) 2014 Actions Semi Inc.
6 * Copyright (c) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
7 */
8
9#ifndef __DT_BINDINGS_ACTIONS_S500_RESET_H
10#define __DT_BINDINGS_ACTIONS_S500_RESET_H
11
12#define RESET_DMAC 0
13#define RESET_NORIF 1
14#define RESET_DDR 2
15#define RESET_NANDC 3
16#define RESET_SD0 4
17#define RESET_SD1 5
18#define RESET_PCM1 6
19#define RESET_DE 7
20#define RESET_LCD 8
21#define RESET_SD2 9
22#define RESET_DSI 10
23#define RESET_CSI 11
24#define RESET_BISP 12
25#define RESET_KEY 13
26#define RESET_GPIO 14
27#define RESET_AUDIO 15
28#define RESET_PCM0 16
29#define RESET_VDE 17
30#define RESET_VCE 18
31#define RESET_GPU3D 19
32#define RESET_NIC301 20
33#define RESET_LENS 21
34#define RESET_PERIPHRESET 22
35#define RESET_USB2_0 23
36#define RESET_TVOUT 24
37#define RESET_HDMI 25
38#define RESET_HDCP2TX 26
39#define RESET_UART6 27
40#define RESET_UART0 28
41#define RESET_UART1 29
42#define RESET_UART2 30
43#define RESET_SPI0 31
44#define RESET_SPI1 32
45#define RESET_SPI2 33
46#define RESET_SPI3 34
47#define RESET_I2C0 35
48#define RESET_I2C1 36
49#define RESET_USB3 37
50#define RESET_UART3 38
51#define RESET_UART4 39
52#define RESET_UART5 40
53#define RESET_I2C2 41
54#define RESET_I2C3 42
55#define RESET_ETHERNET 43
56#define RESET_CHIPID 44
57#define RESET_USB2_1 45
58#define RESET_WD0RESET 46
59#define RESET_WD1RESET 47
60#define RESET_WD2RESET 48
61#define RESET_WD3RESET 49
62#define RESET_DBG0RESET 50
63#define RESET_DBG1RESET 51
64#define RESET_DBG2RESET 52
65#define RESET_DBG3RESET 53
66
67#endif /* __DT_BINDINGS_ACTIONS_S500_RESET_H */
include/linux/clk-provider.h+0−1
@@ -1096,7 +1096,6 @@ int clk_hw_get_parent_index(struct clk_hw *hw); · 1095 unmodified lines
1096int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent);1096int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent);
1097unsigned int __clk_get_enable_count(struct clk *clk);1097unsigned int __clk_get_enable_count(struct clk *clk);
1098unsigned long clk_hw_get_rate(const struct clk_hw *hw);1098unsigned long clk_hw_get_rate(const struct clk_hw *hw);
1099unsigned long __clk_get_flags(struct clk *clk);
1100unsigned long clk_hw_get_flags(const struct clk_hw *hw);1099unsigned long clk_hw_get_flags(const struct clk_hw *hw);
1101#define clk_hw_can_set_rate_parent(hw) \1100#define clk_hw_can_set_rate_parent(hw) \
1102 (clk_hw_get_flags((hw)) & CLK_SET_RATE_PARENT)1101 (clk_hw_get_flags((hw)) & CLK_SET_RATE_PARENT)
include/linux/clk/at91_pmc.h+4−0
@@ -59,6 +59,7 @@ · 58 unmodified lines
59#define AT91_PMC_PLL_UPDT 0x1C /* PMC PLL update register [for SAM9X60] */59#define AT91_PMC_PLL_UPDT 0x1C /* PMC PLL update register [for SAM9X60] */
60#define AT91_PMC_PLL_UPDT_UPDATE (1 << 8) /* Update PLL settings */60#define AT91_PMC_PLL_UPDT_UPDATE (1 << 8) /* Update PLL settings */
61#define AT91_PMC_PLL_UPDT_ID (1 << 0) /* PLL ID */61#define AT91_PMC_PLL_UPDT_ID (1 << 0) /* PLL ID */
62#define AT91_PMC_PLL_UPDT_ID_MSK (0xf) /* PLL ID mask */
62#define AT91_PMC_PLL_UPDT_STUPTIM (0xff << 16) /* Startup time */63#define AT91_PMC_PLL_UPDT_STUPTIM (0xff << 16) /* Startup time */
63 64
64#define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */65#define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */
@@ -136,6 +137,8 @@ · 71 unmodified lines
136#define AT91_PMC_PLLADIV2_ON (1 << 12)137#define AT91_PMC_PLLADIV2_ON (1 << 12)
137#define AT91_PMC_H32MXDIV BIT(24)138#define AT91_PMC_H32MXDIV BIT(24)
138 139
140#define AT91_PMC_XTALF 0x34 /* Main XTAL Frequency Register [SAMA7G5 only] */
141
139#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */142#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */
140#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */143#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
141#define AT91_PMC_USBS_PLLA (0 << 0)144#define AT91_PMC_USBS_PLLA (0 << 0)
@@ -174,6 +177,7 @@ · 32 unmodified lines
174#define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */177#define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */
175#define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */178#define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */
176#define AT91_PMC_GCKRDY (1 << 24) /* Generated Clocks */179#define AT91_PMC_GCKRDY (1 << 24) /* Generated Clocks */
180#define AT91_PMC_MCKXRDY (1 << 26) /* Master Clock x [x=1..4] Ready Status */
177#define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */181#define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */
178 182
179#define AT91_PMC_FSMR 0x70 /* Fast Startup Mode Register */183#define AT91_PMC_FSMR 0x70 /* Fast Startup Mode Register */