History

Merge branches 'clk-stm32f4', 'clk-tegra', 'clk-at91', 'clk-sifive-fu540' and 'clk-spdx' into clk-next

- Support for STM32F769 - Rework AT91 sckc DT bindings - Fix slow RC oscillator issue on sama5d3 - AT91 sam9x60 PMC support - SiFive FU540 PRCI and PLL support * clk-stm32f4: clk: stm32mp1: Add ddrperfm clock clk: stm32: Introduce clocks of STM32F769 board * clk-tegra: clk: tegra: divider: Mark Memory Controller clock as read-only clk: tegra: emc: Replace BUG() with WARN_ONCE() clk: tegra: emc: Fix EMC max-rate clamping clk: tegra: emc: Support multiple RAM codes clk: tegra: emc: Don't enable EMC clock manually clk: tegra124: Remove lock-enable bit from PLLM clk: tegra: Fix PLLM programming on Tegra124+ when PMC overrides divider clk: tegra: Don't enable already enabled PLLs * clk-at91: clk: at91: Mark struct clk_range as const clk: at91: add sam9x60 pmc driver dt-bindings: clk: at91: add bindings for SAM9X60 pmc clk: at91: add sam9x60 PLL driver clk: at91: master: Add sam9x60 support clk: at91: usb: Add sam9x60 support clk: at91: allow configuring generated PCR layout clk: at91: allow configuring peripheral PCR layout clk: at91: sckc: handle different RC startup time clk: at91: modernize sckc binding dt-bindings: clock: at91: new sckc bindings * clk-sifive-fu540: clk: sifive: add a driver for the SiFive FU540 PRCI IP block clk: analogbits: add Wide-Range PLL library dt-bindings: clk: add documentation for the SiFive PRCI driver * clk-spdx: clk: sunxi-ng: Use the correct style for SPDX License Identifier clk: sprd: Use the correct style for SPDX License Identifier clk: renesas: Use the correct style for SPDX License Identifier clk: qcom: Use the correct style for SPDX License Identifier clk: davinci: Use the correct style for SPDX License Identifier clk: actions: Use the correct style for SPDX License Identifier

Stephen Boyd committed 7 years ago

Commit ff060016 parents 5816b74 b06df56 e71f4d3 7b4c162 30b8e27 d65530c59 files · +2424 −259Browse files

Unified · Split

59 files
  1. Documentation/devicetree/bindings/clock/at91-clock.txt +14 −19
  2. Documentation/devicetree/bindings/clock/sifive/fu540-prci.txt +46 −0
  3. Documentation/devicetree/bindings/clock/st,stm32-rcc.txt +6 −0
  4. MAINTAINERS +6 −0
  5. drivers/clk/Kconfig +3 −0
  6. drivers/clk/Makefile +2 −0
  7. drivers/clk/actions/owl-common.h +1 −1
  8. drivers/clk/actions/owl-composite.h +1 −1
  9. drivers/clk/actions/owl-divider.h +1 −1
  10. drivers/clk/actions/owl-factor.h +1 −1
  11. drivers/clk/actions/owl-fixed-factor.h +1 −1
  12. drivers/clk/actions/owl-gate.h +1 −1
  13. drivers/clk/actions/owl-mux.h +1 −1
  14. drivers/clk/actions/owl-pll.h +1 −1
  15. drivers/clk/actions/owl-reset.h +1 −1
  16. drivers/clk/analogbits/Kconfig +2 −0
  17. drivers/clk/analogbits/Makefile +3 −0
  18. drivers/clk/analogbits/wrpll-cln28hpc.c +364 −0
  19. drivers/clk/at91/Makefile +2 −0
  20. drivers/clk/at91/at91sam9260.c +7 −7
  21. drivers/clk/at91/at91sam9rl.c +1 −1
  22. drivers/clk/at91/at91sam9x5.c +10 −1
  23. drivers/clk/at91/clk-generated.c +25 −23
  24. drivers/clk/at91/clk-master.c +5 −3
  25. drivers/clk/at91/clk-peripheral.c +24 −22
  26. drivers/clk/at91/clk-sam9x60-pll.c +330 −0
  27. drivers/clk/at91/clk-usb.c +27 −6
  28. drivers/clk/at91/dt-compat.c +11 −1
  29. drivers/clk/at91/pmc.h +24 −1
  30. drivers/clk/at91/sam9x60.c +307 −0
  31. drivers/clk/at91/sama5d2.c +11 −1
  32. drivers/clk/at91/sama5d4.c +9 −1
  33. drivers/clk/at91/sckc.c +47 −87
  34. drivers/clk/clk-stm32f4.c +299 −8
  35. drivers/clk/clk-stm32mp1.c +3 −0
  36. drivers/clk/davinci/pll.h +1 −1
  37. drivers/clk/davinci/psc.h +1 −1
  38. drivers/clk/qcom/clk-regmap-mux-div.h +1 −1
  39. drivers/clk/renesas/rcar-gen2-cpg.h +2 −2
  40. drivers/clk/renesas/rcar-gen3-cpg.h +2 −2
  41. drivers/clk/renesas/renesas-cpg-mssr.h +2 −2
  42. drivers/clk/sifive/Kconfig +18 −0
  43. drivers/clk/sifive/Makefile +1 −0
  44. drivers/clk/sifive/fu540-prci.c +626 −0
  45. drivers/clk/sprd/common.h +1 −1
  46. drivers/clk/sprd/composite.h +1 −1
  47. drivers/clk/sprd/div.h +1 −1
  48. drivers/clk/sprd/gate.h +1 −1
  49. drivers/clk/sprd/mux.h +1 −1
  50. drivers/clk/sprd/pll.h +1 −1
  51. drivers/clk/sunxi-ng/ccu-sun50i-h6.h +1 −1
  52. drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h +2 −2
  53. drivers/clk/tegra/clk-divider.c +2 −1
  54. drivers/clk/tegra/clk-emc.c +35 −22
  55. drivers/clk/tegra/clk-pll.c +39 −15
  56. drivers/clk/tegra/clk-tegra124.c +1 −2
  57. include/dt-bindings/clock/stm32fx-clock.h +5 −2
  58. include/linux/clk/analogbits-wrpll-cln28hpc.h +79 −0
  59. include/linux/clk/at91_pmc.h +3 −9
Documentation/devicetree/bindings/clock/at91-clock.txt+14−19
@@ -8,35 +8,30 @@ Slow Clock controller: · 7 unmodified lines
88
99 Required properties:
1010 - compatible : shall be one of the following:
11− "atmel,at91sam9x5-sckc" or
11+ "atmel,at91sam9x5-sckc",
12+ "atmel,sama5d3-sckc" or
1213 "atmel,sama5d4-sckc":
1314 at91 SCKC (Slow Clock Controller)
14− This node contains the slow clock definitions.
15−
16− "atmel,at91sam9x5-clk-slow-osc":
17− at91 slow oscillator
18−
19− "atmel,at91sam9x5-clk-slow-rc-osc":
20− at91 internal slow RC oscillator
21−- reg : defines the IO memory reserved for the SCKC.
22−- #size-cells : shall be 0 (reg is used to encode clk id).
23−- #address-cells : shall be 1 (reg is used to encode clk id).
15+- #clock-cells : shall be 0.
16+- clocks : shall be the input parent clock phandle for the clock.
2417
18+Optional properties:
19+- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
20+ provided on XIN.
2521
2622 For example:
27− sckc: sckc@fffffe50 {
28− compatible = "atmel,sama5d3-pmc";
29− reg = <0xfffffe50 0x4>
30− #size-cells = <0>;
31− #address-cells = <1>;
32−
33− /* put at91 slow clocks here */
23+ sckc@fffffe50 {
24+ compatible = "atmel,at91sam9x5-sckc";
25+ reg = <0xfffffe50 0x4>;
26+ clocks = <&slow_xtal>;
27+ #clock-cells = <0>;
3428 };
3529
3630 Power Management Controller (PMC):
3731
3832 Required properties:
39−- compatible : shall be "atmel,<chip>-pmc", "syscon":
33+- compatible : shall be "atmel,<chip>-pmc", "syscon" or
34+ "microchip,sam9x60-pmc"
4035 <chip> can be: at91rm9200, at91sam9260, at91sam9261,
4136 at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15,
4237 at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5,
Documentation/devicetree/bindings/clock/sifive/fu540-prci.txt+46−0
@@ -0,0 +1,46 @@
1+SiFive FU540 PRCI bindings
2+
3+On the FU540 family of SoCs, most system-wide clock and reset integration
4+is via the PRCI IP block.
5+
6+Required properties:
7+- compatible: Should be "sifive,<chip>-prci". Only one value is
8+ supported: "sifive,fu540-c000-prci"
9+- reg: Should describe the PRCI's register target physical address region
10+- clocks: Should point to the hfclk device tree node and the rtcclk
11+ device tree node. The RTC clock here is not a time-of-day clock,
12+ but is instead a high-stability clock source for system timers
13+ and cycle counters.
14+- #clock-cells: Should be <1>
15+
16+The clock consumer should specify the desired clock via the clock ID
17+macros defined in include/dt-bindings/clock/sifive-fu540-prci.h.
18+These macros begin with PRCI_CLK_.
19+
20+The hfclk and rtcclk nodes are required, and represent physical
21+crystals or resonators located on the PCB. These nodes should be present
22+underneath /, rather than /soc.
23+
24+Examples:
25+
26+/* under /, in PCB-specific DT data */
27+hfclk: hfclk {
28+ #clock-cells = <0>;
29+ compatible = "fixed-clock";
30+ clock-frequency = <33333333>;
31+ clock-output-names = "hfclk";
32+};
33+rtcclk: rtcclk {
34+ #clock-cells = <0>;
35+ compatible = "fixed-clock";
36+ clock-frequency = <1000000>;
37+ clock-output-names = "rtcclk";
38+};
39+
40+/* under /soc, in SoC-specific DT data */
41+prci: clock-controller@10000000 {
42+ compatible = "sifive,fu540-c000-prci";
43+ reg = <0x0 0x10000000 0x0 0x1000>;
44+ clocks = <&hfclk>, <&rtcclk>;
45+ #clock-cells = <1>;
46+};
Documentation/devicetree/bindings/clock/st,stm32-rcc.txt+6−0
@@ -11,6 +11,8 @@ Required properties: · 10 unmodified lines
1111 "st,stm32f42xx-rcc"
1212 "st,stm32f469-rcc"
1313 "st,stm32f746-rcc"
14+ "st,stm32f769-rcc"
15+
1416 - reg: should be register base and length as documented in the
1517 datasheet
1618 - #reset-cells: 1, see below
@@ -102,6 +104,10 @@ The secondary index is bound with the following magic numbers: · 85 unmodified lines
102104 28 CLK_I2C3
103105 29 CLK_I2C4
104106 30 CLK_LPTIMER (LPTimer1 clock)
107+ 31 CLK_PLL_SRC
108+ 32 CLK_DFSDM1
109+ 33 CLK_ADFSDM1
110+ 34 CLK_F769_DSI
105111 )
106112
107113 Example:
MAINTAINERS+6−0
@@ -960,6 +960,12 @@ F: drivers/iio/adc/ltc2497* · 959 unmodified lines
960960 X: drivers/iio/*/adjd*
961961 F: drivers/staging/iio/*/ad*
962962
963+ANALOGBITS PLL LIBRARIES
964+M: Paul Walmsley <paul.walmsley@sifive.com>
965+S: Supported
966+F: drivers/clk/analogbits/*
967+F: include/linux/clk/analogbits*
968+
963969 ANDES ARCHITECTURE
964970 M: Greentime Hu <green.hu@gmail.com>
965971 M: Vincent Chen <deanbo422@gmail.com>
drivers/clk/Kconfig+3−0
@@ -1,3 +1,4 @@
1+# SPDX-License-Identifier: GPL-2.0
12
23 config CLKDEV_LOOKUP
34 bool
@@ -304,6 +305,7 @@ config COMMON_CLK_FIXED_MMIO · 300 unmodified lines
304305 Support for Memory Mapped IO Fixed clocks
305306
306307 source "drivers/clk/actions/Kconfig"
308+source "drivers/clk/analogbits/Kconfig"
307309 source "drivers/clk/bcm/Kconfig"
308310 source "drivers/clk/hisilicon/Kconfig"
309311 source "drivers/clk/imgtec/Kconfig"
@@ -316,6 +318,7 @@ source "drivers/clk/mvebu/Kconfig" · 6 unmodified lines
316318 source "drivers/clk/qcom/Kconfig"
317319 source "drivers/clk/renesas/Kconfig"
318320 source "drivers/clk/samsung/Kconfig"
321+source "drivers/clk/sifive/Kconfig"
319322 source "drivers/clk/sprd/Kconfig"
320323 source "drivers/clk/sunxi/Kconfig"
321324 source "drivers/clk/sunxi-ng/Kconfig"
drivers/clk/Makefile+2−0
@@ -66,6 +66,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o · 65 unmodified lines
6666
6767 # please keep this section sorted lexicographically by directory path name
6868 obj-y += actions/
69+obj-y += analogbits/
6970 obj-$(CONFIG_COMMON_CLK_AT91) += at91/
7071 obj-$(CONFIG_ARCH_ARTPEC) += axis/
7172 obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
@@ -95,6 +96,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ · 23 unmodified lines
9596 obj-y += renesas/
9697 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
9798 obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
99+obj-$(CONFIG_CLK_SIFIVE) += sifive/
98100 obj-$(CONFIG_ARCH_SIRF) += sirf/
99101 obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
100102 obj-$(CONFIG_PLAT_SPEAR) += spear/
drivers/clk/actions/owl-common.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL common clock driver
44 //
drivers/clk/actions/owl-composite.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL composite clock driver
44 //
drivers/clk/actions/owl-divider.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL divider clock driver
44 //
drivers/clk/actions/owl-factor.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL factor clock driver
44 //
drivers/clk/actions/owl-fixed-factor.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL fixed factor clock driver
44 //
drivers/clk/actions/owl-gate.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL gate clock driver
44 //
drivers/clk/actions/owl-mux.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL mux clock driver
44 //
drivers/clk/actions/owl-pll.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0+
1+/* SPDX-License-Identifier: GPL-2.0+ */
22 //
33 // OWL pll clock driver
44 //
drivers/clk/actions/owl-reset.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0-or-later
1+/* SPDX-License-Identifier: GPL-2.0-or-later */
22 //
33 // Actions Semi Owl SoCs Reset Management Unit driver
44 //
drivers/clk/analogbits/Kconfig+2−0
@@ -0,0 +1,2 @@
1+config CLK_ANALOGBITS_WRPLL_CLN28HPC
2+ bool
drivers/clk/analogbits/Makefile+3−0
@@ -0,0 +1,3 @@
1+# SPDX-License-Identifier: GPL-2.0
2+
3+obj-$(CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC) += wrpll-cln28hpc.o
drivers/clk/analogbits/wrpll-cln28hpc.c+364−0
@@ -0,0 +1,364 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Copyright (C) 2018-2019 SiFive, Inc.
4+ * Wesley Terpstra
5+ * Paul Walmsley
6+ *
7+ * This library supports configuration parsing and reprogramming of
8+ * the CLN28HPC variant of the Analog Bits Wide Range PLL. The
9+ * intention is for this library to be reusable for any device that
10+ * integrates this PLL; thus the register structure and programming
11+ * details are expected to be provided by a separate IP block driver.
12+ *
13+ * The bulk of this code is primarily useful for clock configurations
14+ * that must operate at arbitrary rates, as opposed to clock configurations
15+ * that are restricted by software or manufacturer guidance to a small,
16+ * pre-determined set of performance points.
17+ *
18+ * References:
19+ * - Analog Bits "Wide Range PLL Datasheet", version 2015.10.01
20+ * - SiFive FU540-C000 Manual v1p0, Chapter 7 "Clocking and Reset"
21+ * https://static.dev.sifive.com/FU540-C000-v1.0.pdf
22+ */
23+
24+#include <linux/bug.h>
25+#include <linux/err.h>
26+#include <linux/log2.h>
27+#include <linux/math64.h>
28+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
29+
30+/* MIN_INPUT_FREQ: minimum input clock frequency, in Hz (Fref_min) */
31+#define MIN_INPUT_FREQ 7000000
32+
33+/* MAX_INPUT_FREQ: maximum input clock frequency, in Hz (Fref_max) */
34+#define MAX_INPUT_FREQ 600000000
35+
36+/* MIN_POST_DIVIDE_REF_FREQ: minimum post-divider reference frequency, in Hz */
37+#define MIN_POST_DIVR_FREQ 7000000
38+
39+/* MAX_POST_DIVIDE_REF_FREQ: maximum post-divider reference frequency, in Hz */
40+#define MAX_POST_DIVR_FREQ 200000000
41+
42+/* MIN_VCO_FREQ: minimum VCO frequency, in Hz (Fvco_min) */
43+#define MIN_VCO_FREQ 2400000000UL
44+
45+/* MAX_VCO_FREQ: maximum VCO frequency, in Hz (Fvco_max) */
46+#define MAX_VCO_FREQ 4800000000ULL
47+
48+/* MAX_DIVQ_DIVISOR: maximum output divisor. Selected by DIVQ = 6 */
49+#define MAX_DIVQ_DIVISOR 64
50+
51+/* MAX_DIVR_DIVISOR: maximum reference divisor. Selected by DIVR = 63 */
52+#define MAX_DIVR_DIVISOR 64
53+
54+/* MAX_LOCK_US: maximum PLL lock time, in microseconds (tLOCK_max) */
55+#define MAX_LOCK_US 70
56+
57+/*
58+ * ROUND_SHIFT: number of bits to shift to avoid precision loss in the rounding
59+ * algorithm
60+ */
61+#define ROUND_SHIFT 20
62+
63+/*
64+ * Private functions
65+ */
66+
67+/**
68+ * __wrpll_calc_filter_range() - determine PLL loop filter bandwidth
69+ * @post_divr_freq: input clock rate after the R divider
70+ *
71+ * Select the value to be presented to the PLL RANGE input signals, based
72+ * on the input clock frequency after the post-R-divider @post_divr_freq.
73+ * This code follows the recommendations in the PLL datasheet for filter
74+ * range selection.
75+ *
76+ * Return: The RANGE value to be presented to the PLL configuration inputs,
77+ * or a negative return code upon error.
78+ */
79+static int __wrpll_calc_filter_range(unsigned long post_divr_freq)
80+{
81+ if (post_divr_freq < MIN_POST_DIVR_FREQ ||
82+ post_divr_freq > MAX_POST_DIVR_FREQ) {
83+ WARN(1, "%s: post-divider reference freq out of range: %lu",
84+ __func__, post_divr_freq);
85+ return -ERANGE;
86+ }
87+
88+ switch (post_divr_freq) {
89+ case 0 ... 10999999:
90+ return 1;
91+ case 11000000 ... 17999999:
92+ return 2;
93+ case 18000000 ... 29999999:
94+ return 3;
95+ case 30000000 ... 49999999:
96+ return 4;
97+ case 50000000 ... 79999999:
98+ return 5;
99+ case 80000000 ... 129999999:
100+ return 6;
101+ }
102+
103+ return 7;
104+}
105+
106+/**
107+ * __wrpll_calc_fbdiv() - return feedback fixed divide value
108+ * @c: ptr to a struct wrpll_cfg record to read from
109+ *
110+ * The internal feedback path includes a fixed by-two divider; the
111+ * external feedback path does not. Return the appropriate divider
112+ * value (2 or 1) depending on whether internal or external feedback
113+ * is enabled. This code doesn't test for invalid configurations
114+ * (e.g. both or neither of WRPLL_FLAGS_*_FEEDBACK are set); it relies
115+ * on the caller to do so.
116+ *
117+ * Context: Any context. Caller must protect the memory pointed to by
118+ * @c from simultaneous modification.
119+ *
120+ * Return: 2 if internal feedback is enabled or 1 if external feedback
121+ * is enabled.
122+ */
123+static u8 __wrpll_calc_fbdiv(const struct wrpll_cfg *c)
124+{
125+ return (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK) ? 2 : 1;
126+}
127+
128+/**
129+ * __wrpll_calc_divq() - determine DIVQ based on target PLL output clock rate
130+ * @target_rate: target PLL output clock rate
131+ * @vco_rate: pointer to a u64 to store the computed VCO rate into
132+ *
133+ * Determine a reasonable value for the PLL Q post-divider, based on the
134+ * target output rate @target_rate for the PLL. Along with returning the
135+ * computed Q divider value as the return value, this function stores the
136+ * desired target VCO rate into the variable pointed to by @vco_rate.
137+ *
138+ * Context: Any context. Caller must protect the memory pointed to by
139+ * @vco_rate from simultaneous access or modification.
140+ *
141+ * Return: a positive integer DIVQ value to be programmed into the hardware
142+ * upon success, or 0 upon error (since 0 is an invalid DIVQ value)
143+ */
144+static u8 __wrpll_calc_divq(u32 target_rate, u64 *vco_rate)
145+{
146+ u64 s;
147+ u8 divq = 0;
148+
149+ if (!vco_rate) {
150+ WARN_ON(1);
151+ goto wcd_out;
152+ }
153+
154+ s = div_u64(MAX_VCO_FREQ, target_rate);
155+ if (s <= 1) {
156+ divq = 1;
157+ *vco_rate = MAX_VCO_FREQ;
158+ } else if (s > MAX_DIVQ_DIVISOR) {
159+ divq = ilog2(MAX_DIVQ_DIVISOR);
160+ *vco_rate = MIN_VCO_FREQ;
161+ } else {
162+ divq = ilog2(s);
163+ *vco_rate = (u64)target_rate << divq;
164+ }
165+
166+wcd_out:
167+ return divq;
168+}
169+
170+/**
171+ * __wrpll_update_parent_rate() - update PLL data when parent rate changes
172+ * @c: ptr to a struct wrpll_cfg record to write PLL data to
173+ * @parent_rate: PLL input refclk rate (pre-R-divider)
174+ *
175+ * Pre-compute some data used by the PLL configuration algorithm when
176+ * the PLL's reference clock rate changes. The intention is to avoid
177+ * computation when the parent rate remains constant - expected to be
178+ * the common case.
179+ *
180+ * Returns: 0 upon success or -ERANGE if the reference clock rate is
181+ * out of range.
182+ */
183+static int __wrpll_update_parent_rate(struct wrpll_cfg *c,
184+ unsigned long parent_rate)
185+{
186+ u8 max_r_for_parent;
187+
188+ if (parent_rate > MAX_INPUT_FREQ || parent_rate < MIN_POST_DIVR_FREQ)
189+ return -ERANGE;
190+
191+ c->parent_rate = parent_rate;
192+ max_r_for_parent = div_u64(parent_rate, MIN_POST_DIVR_FREQ);
193+ c->max_r = min_t(u8, MAX_DIVR_DIVISOR, max_r_for_parent);
194+
195+ c->init_r = DIV_ROUND_UP_ULL(parent_rate, MAX_POST_DIVR_FREQ);
196+
197+ return 0;
198+}
199+
200+/**
201+ * wrpll_configure() - compute PLL configuration for a target rate
202+ * @c: ptr to a struct wrpll_cfg record to write into
203+ * @target_rate: target PLL output clock rate (post-Q-divider)
204+ * @parent_rate: PLL input refclk rate (pre-R-divider)
205+ *
206+ * Compute the appropriate PLL signal configuration values and store
207+ * in PLL context @c. PLL reprogramming is not glitchless, so the
208+ * caller should switch any downstream logic to a different clock
209+ * source or clock-gate it before presenting these values to the PLL
210+ * configuration signals.
211+ *
212+ * The caller must pass this function a pre-initialized struct
213+ * wrpll_cfg record: either initialized to zero (with the
214+ * exception of the .name and .flags fields) or read from the PLL.
215+ *
216+ * Context: Any context. Caller must protect the memory pointed to by @c
217+ * from simultaneous access or modification.
218+ *
219+ * Return: 0 upon success; anything else upon failure.
220+ */
221+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
222+ unsigned long parent_rate)
223+{
224+ unsigned long ratio;
225+ u64 target_vco_rate, delta, best_delta, f_pre_div, vco, vco_pre;
226+ u32 best_f, f, post_divr_freq;
227+ u8 fbdiv, divq, best_r, r;
228+ int range;
229+
230+ if (c->flags == 0) {
231+ WARN(1, "%s called with uninitialized PLL config", __func__);
232+ return -EINVAL;
233+ }
234+
235+ /* Initialize rounding data if it hasn't been initialized already */
236+ if (parent_rate != c->parent_rate) {
237+ if (__wrpll_update_parent_rate(c, parent_rate)) {
238+ pr_err("%s: PLL input rate is out of range\n",
239+ __func__);
240+ return -ERANGE;
241+ }
242+ }
243+
244+ c->flags &= ~WRPLL_FLAGS_RESET_MASK;
245+
246+ /* Put the PLL into bypass if the user requests the parent clock rate */
247+ if (target_rate == parent_rate) {
248+ c->flags |= WRPLL_FLAGS_BYPASS_MASK;
249+ return 0;
250+ }
251+
252+ c->flags &= ~WRPLL_FLAGS_BYPASS_MASK;
253+
254+ /* Calculate the Q shift and target VCO rate */
255+ divq = __wrpll_calc_divq(target_rate, &target_vco_rate);
256+ if (!divq)
257+ return -1;
258+ c->divq = divq;
259+
260+ /* Precalculate the pre-Q divider target ratio */
261+ ratio = div64_u64((target_vco_rate << ROUND_SHIFT), parent_rate);
262+
263+ fbdiv = __wrpll_calc_fbdiv(c);
264+ best_r = 0;
265+ best_f = 0;
266+ best_delta = MAX_VCO_FREQ;
267+
268+ /*
269+ * Consider all values for R which land within
270+ * [MIN_POST_DIVR_FREQ, MAX_POST_DIVR_FREQ]; prefer smaller R
271+ */
272+ for (r = c->init_r; r <= c->max_r; ++r) {
273+ f_pre_div = ratio * r;
274+ f = (f_pre_div + (1 << ROUND_SHIFT)) >> ROUND_SHIFT;
275+ f >>= (fbdiv - 1);
276+
277+ post_divr_freq = div_u64(parent_rate, r);
278+ vco_pre = fbdiv * post_divr_freq;
279+ vco = vco_pre * f;
280+
281+ /* Ensure rounding didn't take us out of range */
282+ if (vco > target_vco_rate) {
283+ --f;
284+ vco = vco_pre * f;
285+ } else if (vco < MIN_VCO_FREQ) {
286+ ++f;
287+ vco = vco_pre * f;
288+ }
289+
290+ delta = abs(target_rate - vco);
291+ if (delta < best_delta) {
292+ best_delta = delta;
293+ best_r = r;
294+ best_f = f;
295+ }
296+ }
297+
298+ c->divr = best_r - 1;
299+ c->divf = best_f - 1;
300+
301+ post_divr_freq = div_u64(parent_rate, best_r);
302+
303+ /* Pick the best PLL jitter filter */
304+ range = __wrpll_calc_filter_range(post_divr_freq);
305+ if (range < 0)
306+ return range;
307+ c->range = range;
308+
309+ return 0;
310+}
311+
312+/**
313+ * wrpll_calc_output_rate() - calculate the PLL's target output rate
314+ * @c: ptr to a struct wrpll_cfg record to read from
315+ * @parent_rate: PLL refclk rate
316+ *
317+ * Given a pointer to the PLL's current input configuration @c and the
318+ * PLL's input reference clock rate @parent_rate (before the R
319+ * pre-divider), calculate the PLL's output clock rate (after the Q
320+ * post-divider).
321+ *
322+ * Context: Any context. Caller must protect the memory pointed to by @c
323+ * from simultaneous modification.
324+ *
325+ * Return: the PLL's output clock rate, in Hz. The return value from
326+ * this function is intended to be convenient to pass directly
327+ * to the Linux clock framework; thus there is no explicit
328+ * error return value.
329+ */
330+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
331+ unsigned long parent_rate)
332+{
333+ u8 fbdiv;
334+ u64 n;
335+
336+ if (c->flags & WRPLL_FLAGS_EXT_FEEDBACK_MASK) {
337+ WARN(1, "external feedback mode not yet supported");
338+ return ULONG_MAX;
339+ }
340+
341+ fbdiv = __wrpll_calc_fbdiv(c);
342+ n = parent_rate * fbdiv * (c->divf + 1);
343+ n = div_u64(n, c->divr + 1);
344+ n >>= c->divq;
345+
346+ return n;
347+}
348+
349+/**
350+ * wrpll_calc_max_lock_us() - return the time for the PLL to lock
351+ * @c: ptr to a struct wrpll_cfg record to read from
352+ *
353+ * Return the minimum amount of time (in microseconds) that the caller
354+ * must wait after reprogramming the PLL to ensure that it is locked
355+ * to the input frequency and stable. This is likely to depend on the DIVR
356+ * value; this is under discussion with the manufacturer.
357+ *
358+ * Return: the minimum amount of time the caller must wait for the PLL
359+ * to lock (in microseconds)
360+ */
361+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c)
362+{
363+ return MAX_LOCK_US;
364+}
drivers/clk/at91/Makefile+2−0
@@ -14,6 +14,8 @@ obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o · 13 unmodified lines
1414 obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
1515 obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
1616 obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o
17+obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o
1718 obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
19+obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o
1820 obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
1921 obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
drivers/clk/at91/at91sam9260.c+7−7
@@ -41,7 +41,7 @@ static u8 sam9260_plla_out[] = { 0, 2 }; · 40 unmodified lines
4141
4242 static u16 sam9260_plla_icpll[] = { 1, 1 };
4343
44−static struct clk_range sam9260_plla_outputs[] = {
44+static const struct clk_range sam9260_plla_outputs[] = {
4545 { .min = 80000000, .max = 160000000 },
4646 { .min = 150000000, .max = 240000000 },
4747 };
@@ -58,7 +58,7 @@ static u8 sam9260_pllb_out[] = { 1 }; · 10 unmodified lines
5858
5959 static u16 sam9260_pllb_icpll[] = { 1 };
6060
61−static struct clk_range sam9260_pllb_outputs[] = {
61+static const struct clk_range sam9260_pllb_outputs[] = {
6262 { .min = 70000000, .max = 130000000 },
6363 };
6464
@@ -128,7 +128,7 @@ static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; · 63 unmodified lines
128128
129129 static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
130130
131−static struct clk_range sam9g20_plla_outputs[] = {
131+static const struct clk_range sam9g20_plla_outputs[] = {
132132 { .min = 745000000, .max = 800000000 },
133133 { .min = 695000000, .max = 750000000 },
134134 { .min = 645000000, .max = 700000000 },
@@ -151,7 +151,7 @@ static u8 sam9g20_pllb_out[] = { 0 }; · 16 unmodified lines
151151
152152 static u16 sam9g20_pllb_icpll[] = { 0 };
153153
154−static struct clk_range sam9g20_pllb_outputs[] = {
154+static const struct clk_range sam9g20_pllb_outputs[] = {
155155 { .min = 30000000, .max = 100000000 },
156156 };
157157
@@ -182,7 +182,7 @@ static const struct clk_master_characteristics sam9261_mck_characteristics = { · 24 unmodified lines
182182 .divisors = { 1, 2, 4, 0 },
183183 };
184184
185−static struct clk_range sam9261_plla_outputs[] = {
185+static const struct clk_range sam9261_plla_outputs[] = {
186186 { .min = 80000000, .max = 200000000 },
187187 { .min = 190000000, .max = 240000000 },
188188 };
@@ -199,7 +199,7 @@ static u8 sam9261_pllb_out[] = { 1 }; · 10 unmodified lines
199199
200200 static u16 sam9261_pllb_icpll[] = { 1 };
201201
202−static struct clk_range sam9261_pllb_outputs[] = {
202+static const struct clk_range sam9261_pllb_outputs[] = {
203203 { .min = 70000000, .max = 130000000 },
204204 };
205205
@@ -262,7 +262,7 @@ static const struct clk_master_characteristics sam9263_mck_characteristics = { · 56 unmodified lines
262262 .divisors = { 1, 2, 4, 0 },
263263 };
264264
265−static struct clk_range sam9263_pll_outputs[] = {
265+static const struct clk_range sam9263_pll_outputs[] = {
266266 { .min = 80000000, .max = 200000000 },
267267 { .min = 190000000, .max = 240000000 },
268268 };
drivers/clk/at91/at91sam9rl.c+1−1
@@ -14,7 +14,7 @@ static const struct clk_master_characteristics sam9rl_mck_characteristics = { · 13 unmodified lines
1414
1515 static u8 sam9rl_plla_out[] = { 0, 2 };
1616
17−static struct clk_range sam9rl_plla_outputs[] = {
17+static const struct clk_range sam9rl_plla_outputs[] = {
1818 { .min = 80000000, .max = 200000000 },
1919 { .min = 190000000, .max = 240000000 },
2020 };
drivers/clk/at91/at91sam9x5.c+10−1
@@ -17,7 +17,7 @@ static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; · 16 unmodified lines
1717
1818 static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
1919
20−static struct clk_range plla_outputs[] = {
20+static const struct clk_range plla_outputs[] = {
2121 { .min = 745000000, .max = 800000000 },
2222 { .min = 695000000, .max = 750000000 },
2323 { .min = 645000000, .max = 700000000 },
@@ -49,6 +49,13 @@ static const struct { · 25 unmodified lines
4949 { .n = "pck1", .p = "prog1", .id = 9 },
5050 };
5151
52+static const struct clk_pcr_layout at91sam9x5_pcr_layout = {
53+ .offset = 0x10c,
54+ .cmd = BIT(12),
55+ .pid_mask = GENMASK(5, 0),
56+ .div_mask = GENMASK(17, 16),
57+};
58+
5259 struct pck {
5360 char *n;
5461 u8 id;
@@ -242,6 +249,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, · 187 unmodified lines
242249
243250 for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
244251 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
252+ &at91sam9x5_pcr_layout,
245253 at91sam9x5_periphck[i].n,
246254 "masterck",
247255 at91sam9x5_periphck[i].id,
@@ -254,6 +262,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, · 6 unmodified lines
254262
255263 for (i = 0; extra_pcks[i].id; i++) {
256264 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
265+ &at91sam9x5_pcr_layout,
257266 extra_pcks[i].n,
258267 "masterck",
259268 extra_pcks[i].id,
drivers/clk/at91/clk-generated.c+25−23
@@ -11,6 +11,7 @@ · 10 unmodified lines
1111 *
1212 */
1313
14+#include <linux/bitfield.h>
1415 #include <linux/clk-provider.h>
1516 #include <linux/clkdev.h>
1617 #include <linux/clk/at91_pmc.h>
@@ -31,6 +32,7 @@ struct clk_generated { · 14 unmodified lines
3132 spinlock_t *lock;
3233 u32 id;
3334 u32 gckdiv;
35+ const struct clk_pcr_layout *layout;
3436 u8 parent_id;
3537 bool audio_pll_allowed;
3638 };
@@ -47,14 +49,14 @@ static int clk_generated_enable(struct clk_hw *hw) · 10 unmodified lines
4749 __func__, gck->gckdiv, gck->parent_id);
4850
4951 spin_lock_irqsave(gck->lock, flags);
50− regmap_write(gck->regmap, AT91_PMC_PCR,
51− (gck->id & AT91_PMC_PCR_PID_MASK));
52− regmap_update_bits(gck->regmap, AT91_PMC_PCR,
53− AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK |
54− AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
55− AT91_PMC_PCR_GCKCSS(gck->parent_id) |
56− AT91_PMC_PCR_CMD |
57− AT91_PMC_PCR_GCKDIV(gck->gckdiv) |
52+ regmap_write(gck->regmap, gck->layout->offset,
53+ (gck->id & gck->layout->pid_mask));
54+ regmap_update_bits(gck->regmap, gck->layout->offset,
55+ AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
56+ gck->layout->cmd | AT91_PMC_PCR_GCKEN,
57+ field_prep(gck->layout->gckcss_mask, gck->parent_id) |
58+ gck->layout->cmd |
59+ FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
5860 AT91_PMC_PCR_GCKEN);
5961 spin_unlock_irqrestore(gck->lock, flags);
6062 return 0;
@@ -66,11 +68,11 @@ static void clk_generated_disable(struct clk_hw *hw) · 5 unmodified lines
6668 unsigned long flags;
6769
6870 spin_lock_irqsave(gck->lock, flags);
69− regmap_write(gck->regmap, AT91_PMC_PCR,
70− (gck->id & AT91_PMC_PCR_PID_MASK));
71− regmap_update_bits(gck->regmap, AT91_PMC_PCR,
72− AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
73− AT91_PMC_PCR_CMD);
71+ regmap_write(gck->regmap, gck->layout->offset,
72+ (gck->id & gck->layout->pid_mask));
73+ regmap_update_bits(gck->regmap, gck->layout->offset,
74+ gck->layout->cmd | AT91_PMC_PCR_GCKEN,
75+ gck->layout->cmd);
7476 spin_unlock_irqrestore(gck->lock, flags);
7577 }
7678
@@ -81,9 +83,9 @@ static int clk_generated_is_enabled(struct clk_hw *hw) · 4 unmodified lines
8183 unsigned int status;
8284
8385 spin_lock_irqsave(gck->lock, flags);
84− regmap_write(gck->regmap, AT91_PMC_PCR,
85− (gck->id & AT91_PMC_PCR_PID_MASK));
86− regmap_read(gck->regmap, AT91_PMC_PCR, &status);
86+ regmap_write(gck->regmap, gck->layout->offset,
87+ (gck->id & gck->layout->pid_mask));
88+ regmap_read(gck->regmap, gck->layout->offset, &status);
8789 spin_unlock_irqrestore(gck->lock, flags);
8890
8991 return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
@@ -259,19 +261,18 @@ static void clk_generated_startup(struct clk_generated *gck) · 169 unmodified lines
259261 unsigned long flags;
260262
261263 spin_lock_irqsave(gck->lock, flags);
262− regmap_write(gck->regmap, AT91_PMC_PCR,
263− (gck->id & AT91_PMC_PCR_PID_MASK));
264− regmap_read(gck->regmap, AT91_PMC_PCR, &tmp);
264+ regmap_write(gck->regmap, gck->layout->offset,
265+ (gck->id & gck->layout->pid_mask));
266+ regmap_read(gck->regmap, gck->layout->offset, &tmp);
265267 spin_unlock_irqrestore(gck->lock, flags);
266268
267− gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
268− >> AT91_PMC_PCR_GCKCSS_OFFSET;
269− gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK)
270− >> AT91_PMC_PCR_GCKDIV_OFFSET;
269+ gck->parent_id = field_get(gck->layout->gckcss_mask, tmp);
270+ gck->gckdiv = FIELD_GET(AT91_PMC_PCR_GCKDIV_MASK, tmp);
271271 }
272272
273273 struct clk_hw * __init
274274 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
275+ const struct clk_pcr_layout *layout,
275276 const char *name, const char **parent_names,
276277 u8 num_parents, u8 id, bool pll_audio,
277278 const struct clk_range *range)
@@ -298,6 +299,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, · 20 unmodified lines
298299 gck->lock = lock;
299300 gck->range = *range;
300301 gck->audio_pll_allowed = pll_audio;
302+ gck->layout = layout;
301303
302304 clk_generated_startup(gck);
303305 hw = &gck->hw;
drivers/clk/at91/clk-master.c+5−3
@@ -29,6 +29,7 @@ struct clk_master { · 28 unmodified lines
2929 struct regmap *regmap;
3030 const struct clk_master_layout *layout;
3131 const struct clk_master_characteristics *characteristics;
32+ u32 mckr;
3233 };
3334
3435 static inline bool clk_master_ready(struct regmap *regmap)
@@ -69,7 +70,7 @@ static unsigned long clk_master_recalc_rate(struct clk_hw *hw, · 34 unmodified lines
6970 master->characteristics;
7071 unsigned int mckr;
7172
72− regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
73+ regmap_read(master->regmap, master->layout->offset, &mckr);
7374 mckr &= layout->mask;
7475
7576 pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
@@ -95,7 +96,7 @@ static u8 clk_master_get_parent(struct clk_hw *hw) · 19 unmodified lines
9596 struct clk_master *master = to_clk_master(hw);
9697 unsigned int mckr;
9798
98− regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
99+ regmap_read(master->regmap, master->layout->offset, &mckr);
99100
100101 return mckr & AT91_PMC_CSS;
101102 }
@@ -147,13 +148,14 @@ at91_clk_register_master(struct regmap *regmap, · 45 unmodified lines
147148 return hw;
148149 }
149150
150−
151151 const struct clk_master_layout at91rm9200_master_layout = {
152152 .mask = 0x31F,
153153 .pres_shift = 2,
154+ .offset = AT91_PMC_MCKR,
154155 };
155156
156157 const struct clk_master_layout at91sam9x5_master_layout = {
157158 .mask = 0x373,
158159 .pres_shift = 4,
160+ .offset = AT91_PMC_MCKR,
159161 };
drivers/clk/at91/clk-peripheral.c+24−22
@@ -8,6 +8,7 @@ · 7 unmodified lines
88 *
99 */
1010
11+#include <linux/bitops.h>
1112 #include <linux/clk-provider.h>
1213 #include <linux/clkdev.h>
1314 #include <linux/clk/at91_pmc.h>
@@ -23,9 +24,6 @@ DEFINE_SPINLOCK(pmc_pcr_lock); · 9 unmodified lines
2324 #define PERIPHERAL_ID_MAX 31
2425 #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
2526
26−#define PERIPHERAL_RSHIFT_MASK 0x3
27−#define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK)
28−
2927 #define PERIPHERAL_MAX_SHIFT 3
3028
3129 struct clk_peripheral {
@@ -43,6 +41,7 @@ struct clk_sam9x5_peripheral { · 11 unmodified lines
4341 spinlock_t *lock;
4442 u32 id;
4543 u32 div;
44+ const struct clk_pcr_layout *layout;
4645 bool auto_div;
4746 };
4847
@@ -169,13 +168,13 @@ static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) · 120 unmodified lines
169168 return 0;
170169
171170 spin_lock_irqsave(periph->lock, flags);
172− regmap_write(periph->regmap, AT91_PMC_PCR,
173− (periph->id & AT91_PMC_PCR_PID_MASK));
174− regmap_update_bits(periph->regmap, AT91_PMC_PCR,
175− AT91_PMC_PCR_DIV_MASK | AT91_PMC_PCR_CMD |
171+ regmap_write(periph->regmap, periph->layout->offset,
172+ (periph->id & periph->layout->pid_mask));
173+ regmap_update_bits(periph->regmap, periph->layout->offset,
174+ periph->layout->div_mask | periph->layout->cmd |
176175 AT91_PMC_PCR_EN,
177− AT91_PMC_PCR_DIV(periph->div) |
178− AT91_PMC_PCR_CMD |
176+ field_prep(periph->layout->div_mask, periph->div) |
177+ periph->layout->cmd |
179178 AT91_PMC_PCR_EN);
180179 spin_unlock_irqrestore(periph->lock, flags);
181180
@@ -191,11 +190,11 @@ static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) · 9 unmodified lines
191190 return;
192191
193192 spin_lock_irqsave(periph->lock, flags);
194− regmap_write(periph->regmap, AT91_PMC_PCR,
195− (periph->id & AT91_PMC_PCR_PID_MASK));
196− regmap_update_bits(periph->regmap, AT91_PMC_PCR,
197− AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD,
198− AT91_PMC_PCR_CMD);
193+ regmap_write(periph->regmap, periph->layout->offset,
194+ (periph->id & periph->layout->pid_mask));
195+ regmap_update_bits(periph->regmap, periph->layout->offset,
196+ AT91_PMC_PCR_EN | periph->layout->cmd,
197+ periph->layout->cmd);
199198 spin_unlock_irqrestore(periph->lock, flags);
200199 }
201200
@@ -209,9 +208,9 @@ static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) · 7 unmodified lines
209208 return 1;
210209
211210 spin_lock_irqsave(periph->lock, flags);
212− regmap_write(periph->regmap, AT91_PMC_PCR,
213− (periph->id & AT91_PMC_PCR_PID_MASK));
214− regmap_read(periph->regmap, AT91_PMC_PCR, &status);
211+ regmap_write(periph->regmap, periph->layout->offset,
212+ (periph->id & periph->layout->pid_mask));
213+ regmap_read(periph->regmap, periph->layout->offset, &status);
215214 spin_unlock_irqrestore(periph->lock, flags);
216215
217216 return status & AT91_PMC_PCR_EN ? 1 : 0;
@@ -229,13 +228,13 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, · 11 unmodified lines
229228 return parent_rate;
230229
231230 spin_lock_irqsave(periph->lock, flags);
232− regmap_write(periph->regmap, AT91_PMC_PCR,
233− (periph->id & AT91_PMC_PCR_PID_MASK));
234− regmap_read(periph->regmap, AT91_PMC_PCR, &status);
231+ regmap_write(periph->regmap, periph->layout->offset,
232+ (periph->id & periph->layout->pid_mask));
233+ regmap_read(periph->regmap, periph->layout->offset, &status);
235234 spin_unlock_irqrestore(periph->lock, flags);
236235
237236 if (status & AT91_PMC_PCR_EN) {
238− periph->div = PERIPHERAL_RSHIFT(status);
237+ periph->div = field_get(periph->layout->div_mask, status);
239238 periph->auto_div = false;
240239 } else {
241240 clk_sam9x5_peripheral_autodiv(periph);
@@ -328,6 +327,7 @@ static const struct clk_ops sam9x5_peripheral_ops = { · 86 unmodified lines
328327
329328 struct clk_hw * __init
330329 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
330+ const struct clk_pcr_layout *layout,
331331 const char *name, const char *parent_name,
332332 u32 id, const struct clk_range *range)
333333 {
@@ -354,7 +354,9 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, · 20 unmodified lines
354354 periph->div = 0;
355355 periph->regmap = regmap;
356356 periph->lock = lock;
357− periph->auto_div = true;
357+ if (layout->div_mask)
358+ periph->auto_div = true;
359+ periph->layout = layout;
358360 periph->range = *range;
359361
360362 hw = &periph->hw;
drivers/clk/at91/clk-sam9x60-pll.c+330−0
@@ -0,0 +1,330 @@
1+// SPDX-License-Identifier: GPL-2.0+
2+/*
3+ * Copyright (C) 2019 Microchip Technology Inc.
4+ *
5+ */
6+
7+#include <linux/bitfield.h>
8+#include <linux/clk-provider.h>
9+#include <linux/clkdev.h>
10+#include <linux/clk/at91_pmc.h>
11+#include <linux/of.h>
12+#include <linux/mfd/syscon.h>
13+#include <linux/regmap.h>
14+
15+#include "pmc.h"
16+
17+#define PMC_PLL_CTRL0 0xc
18+#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
19+#define PMC_PLL_CTRL0_ENPLL BIT(28)
20+#define PMC_PLL_CTRL0_ENPLLCK BIT(29)
21+#define PMC_PLL_CTRL0_ENLOCK BIT(31)
22+
23+#define PMC_PLL_CTRL1 0x10
24+#define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
25+#define PMC_PLL_CTRL1_MUL_MSK GENMASK(30, 24)
26+
27+#define PMC_PLL_ACR 0x18
28+#define PMC_PLL_ACR_DEFAULT 0x1b040010UL
29+#define PMC_PLL_ACR_UTMIVR BIT(12)
30+#define PMC_PLL_ACR_UTMIBG BIT(13)
31+#define PMC_PLL_ACR_LOOP_FILTER_MSK GENMASK(31, 24)
32+
33+#define PMC_PLL_UPDT 0x1c
34+#define PMC_PLL_UPDT_UPDATE BIT(8)
35+
36+#define PMC_PLL_ISR0 0xec
37+
38+#define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
39+#define UPLL_DIV 2
40+#define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
41+
42+#define PLL_MAX_ID 1
43+
44+struct sam9x60_pll {
45+ struct clk_hw hw;
46+ struct regmap *regmap;
47+ spinlock_t *lock;
48+ const struct clk_pll_characteristics *characteristics;
49+ u32 frac;
50+ u8 id;
51+ u8 div;
52+ u16 mul;
53+};
54+
55+#define to_sam9x60_pll(hw) container_of(hw, struct sam9x60_pll, hw)
56+
57+static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
58+{
59+ unsigned int status;
60+
61+ regmap_read(regmap, PMC_PLL_ISR0, &status);
62+
63+ return !!(status & BIT(id));
64+}
65+
66+static int sam9x60_pll_prepare(struct clk_hw *hw)
67+{
68+ struct sam9x60_pll *pll = to_sam9x60_pll(hw);
69+ struct regmap *regmap = pll->regmap;
70+ unsigned long flags;
71+ u8 div;
72+ u16 mul;
73+ u32 val;
74+
75+ spin_lock_irqsave(pll->lock, flags);
76+ regmap_write(regmap, PMC_PLL_UPDT, pll->id);
77+
78+ regmap_read(regmap, PMC_PLL_CTRL0, &val);
79+ div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
80+
81+ regmap_read(regmap, PMC_PLL_CTRL1, &val);
82+ mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
83+
84+ if (sam9x60_pll_ready(regmap, pll->id) &&
85+ (div == pll->div && mul == pll->mul)) {
86+ spin_unlock_irqrestore(pll->lock, flags);
87+ return 0;
88+ }
89+
90+ /* Recommended value for PMC_PLL_ACR */
91+ val = PMC_PLL_ACR_DEFAULT;
92+ regmap_write(regmap, PMC_PLL_ACR, val);
93+
94+ regmap_write(regmap, PMC_PLL_CTRL1,
95+ FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK, pll->mul));
96+
97+ if (pll->characteristics->upll) {
98+ /* Enable the UTMI internal bandgap */
99+ val |= PMC_PLL_ACR_UTMIBG;
100+ regmap_write(regmap, PMC_PLL_ACR, val);
101+
102+ udelay(10);
103+
104+ /* Enable the UTMI internal regulator */
105+ val |= PMC_PLL_ACR_UTMIVR;
106+ regmap_write(regmap, PMC_PLL_ACR, val);
107+
108+ udelay(10);
109+ }
110+
111+ regmap_update_bits(regmap, PMC_PLL_UPDT,
112+ PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
113+
114+ regmap_write(regmap, PMC_PLL_CTRL0,
115+ PMC_PLL_CTRL0_ENLOCK | PMC_PLL_CTRL0_ENPLL |
116+ PMC_PLL_CTRL0_ENPLLCK | pll->div);
117+
118+ regmap_update_bits(regmap, PMC_PLL_UPDT,
119+ PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
120+
121+ while (!sam9x60_pll_ready(regmap, pll->id))
122+ cpu_relax();
123+
124+ spin_unlock_irqrestore(pll->lock, flags);
125+
126+ return 0;
127+}
128+
129+static int sam9x60_pll_is_prepared(struct clk_hw *hw)
130+{
131+ struct sam9x60_pll *pll = to_sam9x60_pll(hw);
132+
133+ return sam9x60_pll_ready(pll->regmap, pll->id);
134+}
135+
136+static void sam9x60_pll_unprepare(struct clk_hw *hw)
137+{
138+ struct sam9x60_pll *pll = to_sam9x60_pll(hw);
139+ unsigned long flags;
140+
141+ spin_lock_irqsave(pll->lock, flags);
142+
143+ regmap_write(pll->regmap, PMC_PLL_UPDT, pll->id);
144+
145+ regmap_update_bits(pll->regmap, PMC_PLL_CTRL0,
146+ PMC_PLL_CTRL0_ENPLLCK, 0);
147+
148+ regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
149+ PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
150+
151+ regmap_update_bits(pll->regmap, PMC_PLL_CTRL0, PMC_PLL_CTRL0_ENPLL, 0);
152+
153+ if (pll->characteristics->upll)
154+ regmap_update_bits(pll->regmap, PMC_PLL_ACR,
155+ PMC_PLL_ACR_UTMIBG | PMC_PLL_ACR_UTMIVR, 0);
156+
157+ regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
158+ PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
159+
160+ spin_unlock_irqrestore(pll->lock, flags);
161+}
162+
163+static unsigned long sam9x60_pll_recalc_rate(struct clk_hw *hw,
164+ unsigned long parent_rate)
165+{
166+ struct sam9x60_pll *pll = to_sam9x60_pll(hw);
167+
168+ return (parent_rate * (pll->mul + 1)) / (pll->div + 1);
169+}
170+
171+static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll,
172+ unsigned long rate,
173+ unsigned long parent_rate,
174+ bool update)
175+{
176+ const struct clk_pll_characteristics *characteristics =
177+ pll->characteristics;
178+ unsigned long bestremainder = ULONG_MAX;
179+ unsigned long maxdiv, mindiv, tmpdiv;
180+ long bestrate = -ERANGE;
181+ unsigned long bestdiv = 0;
182+ unsigned long bestmul = 0;
183+ unsigned long bestfrac = 0;
184+
185+ if (rate < characteristics->output[0].min ||
186+ rate > characteristics->output[0].max)
187+ return -ERANGE;
188+
189+ if (!pll->characteristics->upll) {
190+ mindiv = parent_rate / rate;
191+ if (mindiv < 2)
192+ mindiv = 2;
193+
194+ maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX, rate);
195+ if (maxdiv > PLL_DIV_MAX)
196+ maxdiv = PLL_DIV_MAX;
197+ } else {
198+ mindiv = maxdiv = UPLL_DIV;
199+ }
200+
201+ for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
202+ unsigned long remainder;
203+ unsigned long tmprate;
204+ unsigned long tmpmul;
205+ unsigned long tmpfrac = 0;
206+
207+ /*
208+ * Calculate the multiplier associated with the current
209+ * divider that provide the closest rate to the requested one.
210+ */
211+ tmpmul = mult_frac(rate, tmpdiv, parent_rate);
212+ tmprate = mult_frac(parent_rate, tmpmul, tmpdiv);
213+ remainder = rate - tmprate;
214+
215+ if (remainder) {
216+ tmpfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * tmpdiv * (1 << 22),
217+ parent_rate);
218+
219+ tmprate += DIV_ROUND_CLOSEST_ULL((u64)tmpfrac * parent_rate,
220+ tmpdiv * (1 << 22));
221+
222+ if (tmprate > rate)
223+ remainder = tmprate - rate;
224+ else
225+ remainder = rate - tmprate;
226+ }
227+
228+ /*
229+ * Compare the remainder with the best remainder found until
230+ * now and elect a new best multiplier/divider pair if the
231+ * current remainder is smaller than the best one.
232+ */
233+ if (remainder < bestremainder) {
234+ bestremainder = remainder;
235+ bestdiv = tmpdiv;
236+ bestmul = tmpmul;
237+ bestrate = tmprate;
238+ bestfrac = tmpfrac;
239+ }
240+
241+ /* We've found a perfect match! */
242+ if (!remainder)
243+ break;
244+ }
245+
246+ /* Check if bestrate is a valid output rate */
247+ if (bestrate < characteristics->output[0].min &&
248+ bestrate > characteristics->output[0].max)
249+ return -ERANGE;
250+
251+ if (update) {
252+ pll->div = bestdiv - 1;
253+ pll->mul = bestmul - 1;
254+ pll->frac = bestfrac;
255+ }
256+
257+ return bestrate;
258+}
259+
260+static long sam9x60_pll_round_rate(struct clk_hw *hw, unsigned long rate,
261+ unsigned long *parent_rate)
262+{
263+ struct sam9x60_pll *pll = to_sam9x60_pll(hw);
264+
265+ return sam9x60_pll_get_best_div_mul(pll, rate, *parent_rate, false);
266+}
267+
268+static int sam9x60_pll_set_rate(struct clk_hw *hw, unsigned long rate,
269+ unsigned long parent_rate)
270+{
271+ struct sam9x60_pll *pll = to_sam9x60_pll(hw);
272+
273+ return sam9x60_pll_get_best_div_mul(pll, rate, parent_rate, true);
274+}
275+
276+static const struct clk_ops pll_ops = {
277+ .prepare = sam9x60_pll_prepare,
278+ .unprepare = sam9x60_pll_unprepare,
279+ .is_prepared = sam9x60_pll_is_prepared,
280+ .recalc_rate = sam9x60_pll_recalc_rate,
281+ .round_rate = sam9x60_pll_round_rate,
282+ .set_rate = sam9x60_pll_set_rate,
283+};
284+
285+struct clk_hw * __init
286+sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock,
287+ const char *name, const char *parent_name, u8 id,
288+ const struct clk_pll_characteristics *characteristics)
289+{
290+ struct sam9x60_pll *pll;
291+ struct clk_hw *hw;
292+ struct clk_init_data init;
293+ unsigned int pllr;
294+ int ret;
295+
296+ if (id > PLL_MAX_ID)
297+ return ERR_PTR(-EINVAL);
298+
299+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
300+ if (!pll)
301+ return ERR_PTR(-ENOMEM);
302+
303+ init.name = name;
304+ init.ops = &pll_ops;
305+ init.parent_names = &parent_name;
306+ init.num_parents = 1;
307+ init.flags = CLK_SET_RATE_GATE;
308+
309+ pll->id = id;
310+ pll->hw.init = &init;
311+ pll->characteristics = characteristics;
312+ pll->regmap = regmap;
313+ pll->lock = lock;
314+
315+ regmap_write(regmap, PMC_PLL_UPDT, id);
316+ regmap_read(regmap, PMC_PLL_CTRL0, &pllr);
317+ pll->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, pllr);
318+ regmap_read(regmap, PMC_PLL_CTRL1, &pllr);
319+ pll->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, pllr);
320+
321+ hw = &pll->hw;
322+ ret = clk_hw_register(NULL, hw);
323+ if (ret) {
324+ kfree(pll);
325+ hw = ERR_PTR(ret);
326+ }
327+
328+ return hw;
329+}
330+
drivers/clk/at91/clk-usb.c+27−6
@@ -23,9 +23,13 @@ · 22 unmodified lines
2323 #define RM9200_USB_DIV_SHIFT 28
2424 #define RM9200_USB_DIV_TAB_SIZE 4
2525
26+#define SAM9X5_USBS_MASK GENMASK(0, 0)
27+#define SAM9X60_USBS_MASK GENMASK(1, 0)
28+
2629 struct at91sam9x5_clk_usb {
2730 struct clk_hw hw;
2831 struct regmap *regmap;
32+ u32 usbs_mask;
2933 };
3034
3135 #define to_at91sam9x5_clk_usb(hw) \
@@ -111,8 +115,7 @@ static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) · 79 unmodified lines
111115 if (index > 1)
112116 return -EINVAL;
113117
114− regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
115− index ? AT91_PMC_USBS : 0);
118+ regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index);
116119
117120 return 0;
118121 }
@@ -124,7 +127,7 @@ static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) · 5 unmodified lines
124127
125128 regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
126129
127− return usbr & AT91_PMC_USBS;
130+ return usbr & usb->usbs_mask;
128131 }
129132
130133 static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -190,9 +193,10 @@ static const struct clk_ops at91sam9n12_usb_ops = { · 59 unmodified lines
190193 .set_rate = at91sam9x5_clk_usb_set_rate,
191194 };
192195
193−struct clk_hw * __init
194−at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
195− const char **parent_names, u8 num_parents)
196+static struct clk_hw * __init
197+_at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
198+ const char **parent_names, u8 num_parents,
199+ u32 usbs_mask)
196200 {
197201 struct at91sam9x5_clk_usb *usb;
198202 struct clk_hw *hw;
@@ -212,6 +216,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, · 13 unmodified lines
212216
213217 usb->hw.init = &init;
214218 usb->regmap = regmap;
219+ usb->usbs_mask = SAM9X5_USBS_MASK;
215220
216221 hw = &usb->hw;
217222 ret = clk_hw_register(NULL, &usb->hw);
@@ -223,6 +228,22 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, · 5 unmodified lines
223228 return hw;
224229 }
225230
231+struct clk_hw * __init
232+at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
233+ const char **parent_names, u8 num_parents)
234+{
235+ return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
236+ num_parents, SAM9X5_USBS_MASK);
237+}
238+
239+struct clk_hw * __init
240+sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
241+ const char **parent_names, u8 num_parents)
242+{
243+ return _at91sam9x5_clk_register_usb(regmap, name, parent_names,
244+ num_parents, SAM9X60_USBS_MASK);
245+}
246+
226247 struct clk_hw * __init
227248 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
228249 const char *parent_name)
drivers/clk/at91/dt-compat.c+11−1
@@ -93,6 +93,14 @@ CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup, · 92 unmodified lines
9393 of_sama5d2_clk_audio_pll_pmc_setup);
9494 #endif /* CONFIG_HAVE_AT91_AUDIO_PLL */
9595
96+static const struct clk_pcr_layout dt_pcr_layout = {
97+ .offset = 0x10c,
98+ .cmd = BIT(12),
99+ .pid_mask = GENMASK(5, 0),
100+ .div_mask = GENMASK(17, 16),
101+ .gckcss_mask = GENMASK(10, 8),
102+};
103+
96104 #ifdef CONFIG_HAVE_AT91_GENERATED_CLK
97105 #define GENERATED_SOURCE_MAX 6
98106
@@ -146,7 +154,8 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) · 47 unmodified lines
146154 id == GCK_ID_CLASSD))
147155 pll_audio = true;
148156
149− hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
157+ hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
158+ &dt_pcr_layout, name,
150159 parent_names, num_parents,
151160 id, pll_audio, &range);
152161 if (IS_ERR(hw))
@@ -448,6 +457,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type) · 295 unmodified lines
448457
449458 hw = at91_clk_register_sam9x5_peripheral(regmap,
450459 &pmc_pcr_lock,
460+ &dt_pcr_layout,
451461 name,
452462 parent_name,
453463 id, &range);
drivers/clk/at91/pmc.h+24−1
@@ -38,6 +38,7 @@ struct clk_range { · 37 unmodified lines
3838 #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
3939
4040 struct clk_master_layout {
41+ u32 offset;
4142 u32 mask;
4243 u8 pres_shift;
4344 };
@@ -65,9 +66,10 @@ extern const struct clk_pll_layout sama5d3_pll_layout; · 21 unmodified lines
6566 struct clk_pll_characteristics {
6667 struct clk_range input;
6768 int num_output;
68− struct clk_range *output;
69+ const struct clk_range *output;
6970 u16 *icpll;
7071 u8 *out;
72+ u8 upll : 1;
7173 };
7274
7375 struct clk_programmable_layout {
@@ -82,6 +84,17 @@ extern const struct clk_programmable_layout at91rm9200_programmable_layout; · 8 unmodified lines
8284 extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
8385 extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
8486
87+struct clk_pcr_layout {
88+ u32 offset;
89+ u32 cmd;
90+ u32 div_mask;
91+ u32 gckcss_mask;
92+ u32 pid_mask;
93+};
94+
95+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
96+#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
97+
8598 #define ndck(a, s) (a[s - 1].id + 1)
8699 #define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
87100 struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
@@ -107,6 +120,7 @@ at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name, · 19 unmodified lines
107120
108121 struct clk_hw * __init
109122 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
123+ const struct clk_pcr_layout *layout,
110124 const char *name, const char **parent_names,
111125 u8 num_parents, u8 id, bool pll_audio,
112126 const struct clk_range *range);
@@ -145,6 +159,7 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name, · 32 unmodified lines
145159 const char *parent_name, u32 id);
146160 struct clk_hw * __init
147161 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
162+ const struct clk_pcr_layout *layout,
148163 const char *name, const char *parent_name,
149164 u32 id, const struct clk_range *range);
150165
@@ -157,6 +172,11 @@ struct clk_hw * __init · 6 unmodified lines
157172 at91_clk_register_plldiv(struct regmap *regmap, const char *name,
158173 const char *parent_name);
159174
175+struct clk_hw * __init
176+sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock,
177+ const char *name, const char *parent_name, u8 id,
178+ const struct clk_pll_characteristics *characteristics);
179+
160180 struct clk_hw * __init
161181 at91_clk_register_programmable(struct regmap *regmap, const char *name,
162182 const char **parent_names, u8 num_parents, u8 id,
@@ -183,6 +203,9 @@ struct clk_hw * __init · 20 unmodified lines
183203 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
184204 const char *parent_name);
185205 struct clk_hw * __init
206+sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
207+ const char **parent_names, u8 num_parents);
208+struct clk_hw * __init
186209 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
187210 const char *parent_name, const u32 *divisors);
188211
drivers/clk/at91/sam9x60.c+307−0
@@ -0,0 +1,307 @@
1+// SPDX-License-Identifier: GPL-2.0
2+#include <linux/clk-provider.h>
3+#include <linux/mfd/syscon.h>
4+#include <linux/slab.h>
5+
6+#include <dt-bindings/clock/at91.h>
7+
8+#include "pmc.h"
9+
10+static DEFINE_SPINLOCK(pmc_pll_lock);
11+
12+static const struct clk_master_characteristics mck_characteristics = {
13+ .output = { .min = 140000000, .max = 200000000 },
14+ .divisors = { 1, 2, 4, 3 },
15+ .have_div3_pres = 1,
16+};
17+
18+static const struct clk_master_layout sam9x60_master_layout = {
19+ .mask = 0x373,
20+ .pres_shift = 4,
21+ .offset = 0x28,
22+};
23+
24+static const struct clk_range plla_outputs[] = {
25+ { .min = 300000000, .max = 600000000 },
26+};
27+
28+static const struct clk_pll_characteristics plla_characteristics = {
29+ .input = { .min = 12000000, .max = 48000000 },
30+ .num_output = ARRAY_SIZE(plla_outputs),
31+ .output = plla_outputs,
32+};
33+
34+static const struct clk_range upll_outputs[] = {
35+ { .min = 300000000, .max = 500000000 },
36+};
37+
38+static const struct clk_pll_characteristics upll_characteristics = {
39+ .input = { .min = 12000000, .max = 48000000 },
40+ .num_output = ARRAY_SIZE(upll_outputs),
41+ .output = upll_outputs,
42+ .upll = true,
43+};
44+
45+static const struct clk_programmable_layout sam9x60_programmable_layout = {
46+ .pres_shift = 8,
47+ .css_mask = 0x1f,
48+ .have_slck_mck = 0,
49+};
50+
51+static const struct clk_pcr_layout sam9x60_pcr_layout = {
52+ .offset = 0x88,
53+ .cmd = BIT(31),
54+ .gckcss_mask = GENMASK(12, 8),
55+ .pid_mask = GENMASK(6, 0),
56+};
57+
58+static const struct {
59+ char *n;
60+ char *p;
61+ u8 id;
62+} sam9x60_systemck[] = {
63+ { .n = "ddrck", .p = "masterck", .id = 2 },
64+ { .n = "uhpck", .p = "usbck", .id = 6 },
65+ { .n = "pck0", .p = "prog0", .id = 8 },
66+ { .n = "pck1", .p = "prog1", .id = 9 },
67+ { .n = "qspick", .p = "masterck", .id = 19 },
68+};
69+
70+static const struct {
71+ char *n;
72+ u8 id;
73+} sam9x60_periphck[] = {
74+ { .n = "pioA_clk", .id = 2, },
75+ { .n = "pioB_clk", .id = 3, },
76+ { .n = "pioC_clk", .id = 4, },
77+ { .n = "flex0_clk", .id = 5, },
78+ { .n = "flex1_clk", .id = 6, },
79+ { .n = "flex2_clk", .id = 7, },
80+ { .n = "flex3_clk", .id = 8, },
81+ { .n = "flex6_clk", .id = 9, },
82+ { .n = "flex7_clk", .id = 10, },
83+ { .n = "flex8_clk", .id = 11, },
84+ { .n = "sdmmc0_clk", .id = 12, },
85+ { .n = "flex4_clk", .id = 13, },
86+ { .n = "flex5_clk", .id = 14, },
87+ { .n = "flex9_clk", .id = 15, },
88+ { .n = "flex10_clk", .id = 16, },
89+ { .n = "tcb0_clk", .id = 17, },
90+ { .n = "pwm_clk", .id = 18, },
91+ { .n = "adc_clk", .id = 19, },
92+ { .n = "dma0_clk", .id = 20, },
93+ { .n = "matrix_clk", .id = 21, },
94+ { .n = "uhphs_clk", .id = 22, },
95+ { .n = "udphs_clk", .id = 23, },
96+ { .n = "macb0_clk", .id = 24, },
97+ { .n = "lcd_clk", .id = 25, },
98+ { .n = "sdmmc1_clk", .id = 26, },
99+ { .n = "macb1_clk", .id = 27, },
100+ { .n = "ssc_clk", .id = 28, },
101+ { .n = "can0_clk", .id = 29, },
102+ { .n = "can1_clk", .id = 30, },
103+ { .n = "flex11_clk", .id = 32, },
104+ { .n = "flex12_clk", .id = 33, },
105+ { .n = "i2s_clk", .id = 34, },
106+ { .n = "qspi_clk", .id = 35, },
107+ { .n = "gfx2d_clk", .id = 36, },
108+ { .n = "pit64b_clk", .id = 37, },
109+ { .n = "trng_clk", .id = 38, },
110+ { .n = "aes_clk", .id = 39, },
111+ { .n = "tdes_clk", .id = 40, },
112+ { .n = "sha_clk", .id = 41, },
113+ { .n = "classd_clk", .id = 42, },
114+ { .n = "isi_clk", .id = 43, },
115+ { .n = "pioD_clk", .id = 44, },
116+ { .n = "tcb1_clk", .id = 45, },
117+ { .n = "dbgu_clk", .id = 47, },
118+ { .n = "mpddr_clk", .id = 49, },
119+};
120+
121+static const struct {
122+ char *n;
123+ u8 id;
124+ struct clk_range r;
125+ bool pll;
126+} sam9x60_gck[] = {
127+ { .n = "flex0_gclk", .id = 5, },
128+ { .n = "flex1_gclk", .id = 6, },
129+ { .n = "flex2_gclk", .id = 7, },
130+ { .n = "flex3_gclk", .id = 8, },
131+ { .n = "flex6_gclk", .id = 9, },
132+ { .n = "flex7_gclk", .id = 10, },
133+ { .n = "flex8_gclk", .id = 11, },
134+ { .n = "sdmmc0_gclk", .id = 12, .r = { .min = 0, .max = 105000000 }, },
135+ { .n = "flex4_gclk", .id = 13, },
136+ { .n = "flex5_gclk", .id = 14, },
137+ { .n = "flex9_gclk", .id = 15, },
138+ { .n = "flex10_gclk", .id = 16, },
139+ { .n = "tcb0_gclk", .id = 17, },
140+ { .n = "adc_gclk", .id = 19, },
141+ { .n = "lcd_gclk", .id = 25, .r = { .min = 0, .max = 140000000 }, },
142+ { .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, },
143+ { .n = "flex11_gclk", .id = 32, },
144+ { .n = "flex12_gclk", .id = 33, },
145+ { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 },
146+ .pll = true, },
147+ { .n = "pit64b_gclk", .id = 37, },
148+ { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 },
149+ .pll = true, },
150+ { .n = "tcb1_gclk", .id = 45, },
151+ { .n = "dbgu_gclk", .id = 47, },
152+};
153+
154+static void __init sam9x60_pmc_setup(struct device_node *np)
155+{
156+ struct clk_range range = CLK_RANGE(0, 0);
157+ const char *td_slck_name, *md_slck_name, *mainxtal_name;
158+ struct pmc_data *sam9x60_pmc;
159+ const char *parent_names[6];
160+ struct regmap *regmap;
161+ struct clk_hw *hw;
162+ int i;
163+ bool bypass;
164+
165+ i = of_property_match_string(np, "clock-names", "td_slck");
166+ if (i < 0)
167+ return;
168+
169+ td_slck_name = of_clk_get_parent_name(np, i);
170+
171+ i = of_property_match_string(np, "clock-names", "md_slck");
172+ if (i < 0)
173+ return;
174+
175+ md_slck_name = of_clk_get_parent_name(np, i);
176+
177+ i = of_property_match_string(np, "clock-names", "main_xtal");
178+ if (i < 0)
179+ return;
180+ mainxtal_name = of_clk_get_parent_name(np, i);
181+
182+ regmap = syscon_node_to_regmap(np);
183+ if (IS_ERR(regmap))
184+ return;
185+
186+ sam9x60_pmc = pmc_data_allocate(PMC_MAIN + 1,
187+ nck(sam9x60_systemck),
188+ nck(sam9x60_periphck),
189+ nck(sam9x60_gck));
190+ if (!sam9x60_pmc)
191+ return;
192+
193+ hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 24000000,
194+ 50000000);
195+ if (IS_ERR(hw))
196+ goto err_free;
197+
198+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
199+
200+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
201+ bypass);
202+ if (IS_ERR(hw))
203+ goto err_free;
204+
205+ parent_names[0] = "main_rc_osc";
206+ parent_names[1] = "main_osc";
207+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
208+ if (IS_ERR(hw))
209+ goto err_free;
210+
211+ sam9x60_pmc->chws[PMC_MAIN] = hw;
212+
213+ hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "pllack",
214+ "mainck", 0, &plla_characteristics);
215+ if (IS_ERR(hw))
216+ goto err_free;
217+
218+ hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "upllck",
219+ "main_osc", 1, &upll_characteristics);
220+ if (IS_ERR(hw))
221+ goto err_free;
222+
223+ sam9x60_pmc->chws[PMC_UTMI] = hw;
224+
225+ parent_names[0] = md_slck_name;
226+ parent_names[1] = "mainck";
227+ parent_names[2] = "pllack";
228+ hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
229+ &sam9x60_master_layout,
230+ &mck_characteristics);
231+ if (IS_ERR(hw))
232+ goto err_free;
233+
234+ sam9x60_pmc->chws[PMC_MCK] = hw;
235+
236+ parent_names[0] = "pllack";
237+ parent_names[1] = "upllck";
238+ parent_names[2] = "mainck";
239+ parent_names[3] = "mainck";
240+ hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 4);
241+ if (IS_ERR(hw))
242+ goto err_free;
243+
244+ parent_names[0] = md_slck_name;
245+ parent_names[1] = td_slck_name;
246+ parent_names[2] = "mainck";
247+ parent_names[3] = "masterck";
248+ parent_names[4] = "pllack";
249+ parent_names[5] = "upllck";
250+ for (i = 0; i < 8; i++) {
251+ char name[6];
252+
253+ snprintf(name, sizeof(name), "prog%d", i);
254+
255+ hw = at91_clk_register_programmable(regmap, name,
256+ parent_names, 6, i,
257+ &sam9x60_programmable_layout);
258+ if (IS_ERR(hw))
259+ goto err_free;
260+ }
261+
262+ for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
263+ hw = at91_clk_register_system(regmap, sam9x60_systemck[i].n,
264+ sam9x60_systemck[i].p,
265+ sam9x60_systemck[i].id);
266+ if (IS_ERR(hw))
267+ goto err_free;
268+
269+ sam9x60_pmc->shws[sam9x60_systemck[i].id] = hw;
270+ }
271+
272+ for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) {
273+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
274+ &sam9x60_pcr_layout,
275+ sam9x60_periphck[i].n,
276+ "masterck",
277+ sam9x60_periphck[i].id,
278+ &range);
279+ if (IS_ERR(hw))
280+ goto err_free;
281+
282+ sam9x60_pmc->phws[sam9x60_periphck[i].id] = hw;
283+ }
284+
285+ for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) {
286+ hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
287+ &sam9x60_pcr_layout,
288+ sam9x60_gck[i].n,
289+ parent_names, 6,
290+ sam9x60_gck[i].id,
291+ sam9x60_gck[i].pll,
292+ &sam9x60_gck[i].r);
293+ if (IS_ERR(hw))
294+ goto err_free;
295+
296+ sam9x60_pmc->ghws[sam9x60_gck[i].id] = hw;
297+ }
298+
299+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sam9x60_pmc);
300+
301+ return;
302+
303+err_free:
304+ pmc_data_free(sam9x60_pmc);
305+}
306+/* Some clks are used for a clocksource */
307+CLK_OF_DECLARE(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup);
drivers/clk/at91/sama5d2.c+11−1
@@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 }; · 15 unmodified lines
1616
1717 static u16 plla_icpll[] = { 0 };
1818
19−static struct clk_range plla_outputs[] = {
19+static const struct clk_range plla_outputs[] = {
2020 { .min = 600000000, .max = 1200000000 },
2121 };
2222
@@ -28,6 +28,13 @@ static const struct clk_pll_characteristics plla_characteristics = { · 5 unmodified lines
2828 .out = plla_out,
2929 };
3030
31+static const struct clk_pcr_layout sama5d2_pcr_layout = {
32+ .offset = 0x10c,
33+ .cmd = BIT(12),
34+ .gckcss_mask = GENMASK(10, 8),
35+ .pid_mask = GENMASK(6, 0),
36+};
37+
3138 static const struct {
3239 char *n;
3340 char *p;
@@ -274,6 +281,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 240 unmodified lines
274281
275282 for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) {
276283 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
284+ &sama5d2_pcr_layout,
277285 sama5d2_periphck[i].n,
278286 "masterck",
279287 sama5d2_periphck[i].id,
@@ -286,6 +294,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 6 unmodified lines
286294
287295 for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) {
288296 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
297+ &sama5d2_pcr_layout,
289298 sama5d2_periph32ck[i].n,
290299 "h32mxck",
291300 sama5d2_periph32ck[i].id,
@@ -304,6 +313,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) · 12 unmodified lines
304313 parent_names[5] = "audiopll_pmcck";
305314 for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
306315 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
316+ &sama5d2_pcr_layout,
307317 sama5d2_gck[i].n,
308318 parent_names, 6,
309319 sama5d2_gck[i].id,
drivers/clk/at91/sama5d4.c+9−1
@@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 }; · 15 unmodified lines
1616
1717 static u16 plla_icpll[] = { 0 };
1818
19−static struct clk_range plla_outputs[] = {
19+static const struct clk_range plla_outputs[] = {
2020 { .min = 600000000, .max = 1200000000 },
2121 };
2222
@@ -28,6 +28,12 @@ static const struct clk_pll_characteristics plla_characteristics = { · 5 unmodified lines
2828 .out = plla_out,
2929 };
3030
31+static const struct clk_pcr_layout sama5d4_pcr_layout = {
32+ .offset = 0x10c,
33+ .cmd = BIT(12),
34+ .pid_mask = GENMASK(6, 0),
35+};
36+
3137 static const struct {
3238 char *n;
3339 char *p;
@@ -232,6 +238,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) · 198 unmodified lines
232238
233239 for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) {
234240 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
241+ &sama5d4_pcr_layout,
235242 sama5d4_periphck[i].n,
236243 "masterck",
237244 sama5d4_periphck[i].id,
@@ -244,6 +251,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) · 6 unmodified lines
244251
245252 for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) {
246253 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
254+ &sama5d4_pcr_layout,
247255 sama5d4_periph32ck[i].n,
248256 "h32mxck",
249257 sama5d4_periph32ck[i].id,
drivers/clk/at91/sckc.c+47−87
@@ -152,28 +152,6 @@ at91_clk_register_slow_osc(void __iomem *sckcr, · 151 unmodified lines
152152 return hw;
153153 }
154154
155−static void __init
156−of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, void __iomem *sckcr)
157−{
158− struct clk_hw *hw;
159− const char *parent_name;
160− const char *name = np->name;
161− u32 startup;
162− bool bypass;
163−
164− parent_name = of_clk_get_parent_name(np, 0);
165− of_property_read_string(np, "clock-output-names", &name);
166− of_property_read_u32(np, "atmel,startup-time-usec", &startup);
167− bypass = of_property_read_bool(np, "atmel,osc-bypass");
168−
169− hw = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
170− bypass);
171− if (IS_ERR(hw))
172− return;
173−
174− of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
175−}
176−
177155 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
178156 unsigned long parent_rate)
179157 {
@@ -266,28 +244,6 @@ at91_clk_register_slow_rc_osc(void __iomem *sckcr, · 86 unmodified lines
266244 return hw;
267245 }
268246
269−static void __init
270−of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, void __iomem *sckcr)
271−{
272− struct clk_hw *hw;
273− u32 frequency = 0;
274− u32 accuracy = 0;
275− u32 startup = 0;
276− const char *name = np->name;
277−
278− of_property_read_string(np, "clock-output-names", &name);
279− of_property_read_u32(np, "clock-frequency", &frequency);
280− of_property_read_u32(np, "clock-accuracy", &accuracy);
281− of_property_read_u32(np, "atmel,startup-time-usec", &startup);
282−
283− hw = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
284− startup);
285− if (IS_ERR(hw))
286− return;
287−
288− of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
289−}
290−
291247 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
292248 {
293249 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
@@ -365,68 +321,72 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr, · 71 unmodified lines
365321 return hw;
366322 }
367323
368−static void __init
369−of_at91sam9x5_clk_slow_setup(struct device_node *np, void __iomem *sckcr)
324+static void __init at91sam9x5_sckc_register(struct device_node *np,
325+ unsigned int rc_osc_startup_us)
370326 {
327+ const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
328+ void __iomem *regbase = of_iomap(np, 0);
329+ struct device_node *child = NULL;
330+ const char *xtal_name;
371331 struct clk_hw *hw;
372− const char *parent_names[2];
373− unsigned int num_parents;
374− const char *name = np->name;
332+ bool bypass;
375333
376− num_parents = of_clk_get_parent_count(np);
377− if (num_parents == 0 || num_parents > 2)
334+ if (!regbase)
335+ return;
336+
337+ hw = at91_clk_register_slow_rc_osc(regbase, parent_names[0], 32768,
338+ 50000000, rc_osc_startup_us);
339+ if (IS_ERR(hw))
378340 return;
379341
380− of_clk_parent_fill(np, parent_names, num_parents);
342+ xtal_name = of_clk_get_parent_name(np, 0);
343+ if (!xtal_name) {
344+ /* DT backward compatibility */
345+ child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc");
346+ if (!child)
347+ return;
348+
349+ xtal_name = of_clk_get_parent_name(child, 0);
350+ bypass = of_property_read_bool(child, "atmel,osc-bypass");
351+
352+ child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow");
353+ } else {
354+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
355+ }
356+
357+ if (!xtal_name)
358+ return;
381359
382− of_property_read_string(np, "clock-output-names", &name);
360+ hw = at91_clk_register_slow_osc(regbase, parent_names[1], xtal_name,
361+ 1200000, bypass);
362+ if (IS_ERR(hw))
363+ return;
383364
384− hw = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
385− num_parents);
365+ hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2);
386366 if (IS_ERR(hw))
387367 return;
388368
389369 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
390−}
391370
392−static const struct of_device_id sckc_clk_ids[] __initconst = {
393− /* Slow clock */
394− {
395− .compatible = "atmel,at91sam9x5-clk-slow-osc",
396− .data = of_at91sam9x5_clk_slow_osc_setup,
397− },
398− {
399− .compatible = "atmel,at91sam9x5-clk-slow-rc-osc",
400− .data = of_at91sam9x5_clk_slow_rc_osc_setup,
401− },
402− {
403− .compatible = "atmel,at91sam9x5-clk-slow",
404− .data = of_at91sam9x5_clk_slow_setup,
405− },
406− { /*sentinel*/ }
407−};
371+ /* DT backward compatibility */
372+ if (child)
373+ of_clk_add_hw_provider(child, of_clk_hw_simple_get, hw);
374+}
408375
409376 static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
410377 {
411− struct device_node *childnp;
412− void (*clk_setup)(struct device_node *, void __iomem *);
413− const struct of_device_id *clk_id;
414− void __iomem *regbase = of_iomap(np, 0);
415−
416− if (!regbase)
417− return;
418−
419− for_each_child_of_node(np, childnp) {
420− clk_id = of_match_node(sckc_clk_ids, childnp);
421− if (!clk_id)
422− continue;
423− clk_setup = clk_id->data;
424− clk_setup(childnp, regbase);
425− }
378+ at91sam9x5_sckc_register(np, 75);
426379 }
427380 CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
428381 of_at91sam9x5_sckc_setup);
429382
383+static void __init of_sama5d3_sckc_setup(struct device_node *np)
384+{
385+ at91sam9x5_sckc_register(np, 500);
386+}
387+CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc",
388+ of_sama5d3_sckc_setup);
389+
430390 static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
431391 {
432392 struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
drivers/clk/clk-stm32f4.c+299−8
@@ -300,6 +300,85 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = { · 299 unmodified lines
300300 { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
301301 };
302302
303+static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
304+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
305+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
306+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
307+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
308+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
309+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
310+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
311+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
312+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
313+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
314+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
315+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
316+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
317+ { STM32F4_RCC_AHB1ENR, 20, "dtcmram", "ahb_div" },
318+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
319+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
320+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
321+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
322+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
323+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
324+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
325+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
326+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
327+
328+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
329+ { STM32F4_RCC_AHB2ENR, 1, "jpeg", "ahb_div" },
330+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
331+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
332+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
333+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
334+
335+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
336+ CLK_IGNORE_UNUSED },
337+ { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
338+ CLK_IGNORE_UNUSED },
339+
340+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
341+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
342+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
343+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
344+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
345+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
346+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
347+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
348+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
349+ { STM32F4_RCC_APB1ENR, 10, "rtcapb", "apb1_mul" },
350+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
351+ { STM32F4_RCC_APB1ENR, 13, "can3", "apb1_div" },
352+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
353+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
354+ { STM32F4_RCC_APB1ENR, 16, "spdifrx", "apb1_div" },
355+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
356+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
357+ { STM32F4_RCC_APB1ENR, 27, "cec", "apb1_div" },
358+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
359+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
360+
361+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
362+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
363+ { STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux2" },
364+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
365+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
366+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
367+ { STM32F4_RCC_APB2ENR, 11, "sdmmc1", "sdmux1" },
368+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
369+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
370+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
371+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
372+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
373+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
374+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
375+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
376+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
377+ { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
378+ { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
379+ { STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" },
380+};
381+
303382 /*
304383 * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
305384 * have gate bits associated with them. Its combined hweight is 71.
@@ -318,6 +397,10 @@ static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull, · 12 unmodified lines
318397 0x0000000000000003ull,
319398 0x04f77f833e01c9ffull };
320399
400+static const u64 stm32f769_gate_map[MAX_GATE_MAP] = { 0x000000f37ef417ffull,
401+ 0x0000000000000003ull,
402+ 0x44F77F833E01EDFFull };
403+
321404 static const u64 *stm32f4_gate_map;
322405
323406 static struct clk_hw **clks;
@@ -1048,6 +1131,10 @@ static const char *rtc_parents[4] = { · 724 unmodified lines
10481131 "no-clock", "lse", "lsi", "hse-rtc"
10491132 };
10501133
1134+static const char *pll_src = "pll-src";
1135+
1136+static const char *pllsrc_parent[2] = { "hsi", NULL };
1137+
10511138 static const char *dsi_parent[2] = { NULL, "pll-r" };
10521139
10531140 static const char *lcd_parent[1] = { "pllsai-r-div" };
@@ -1072,6 +1159,9 @@ static const char *uart_parents2[4] = { "apb1_div", "sys", "hsi", "lse" }; · 18 unmodified lines
10721159
10731160 static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" };
10741161
1162+static const char * const dfsdm1_src[] = { "apb2_div", "sys" };
1163+static const char * const adsfdm1_parent[] = { "sai1_clk", "sai2_clk" };
1164+
10751165 struct stm32_aux_clk {
10761166 int idx;
10771167 const char *name;
@@ -1313,6 +1403,177 @@ static const struct stm32_aux_clk stm32f746_aux_clk[] = { · 235 unmodified lines
13131403 },
13141404 };
13151405
1406+static const struct stm32_aux_clk stm32f769_aux_clk[] = {
1407+ {
1408+ CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1409+ NO_MUX, 0, 0,
1410+ STM32F4_RCC_APB2ENR, 26,
1411+ CLK_SET_RATE_PARENT
1412+ },
1413+ {
1414+ CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
1415+ STM32F4_RCC_CFGR, 23, 1,
1416+ NO_GATE, 0,
1417+ CLK_SET_RATE_PARENT
1418+ },
1419+ {
1420+ CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents),
1421+ STM32F4_RCC_DCKCFGR, 20, 3,
1422+ STM32F4_RCC_APB2ENR, 22,
1423+ CLK_SET_RATE_PARENT
1424+ },
1425+ {
1426+ CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents),
1427+ STM32F4_RCC_DCKCFGR, 22, 3,
1428+ STM32F4_RCC_APB2ENR, 23,
1429+ CLK_SET_RATE_PARENT
1430+ },
1431+ {
1432+ NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
1433+ STM32F7_RCC_DCKCFGR2, 27, 1,
1434+ NO_GATE, 0,
1435+ 0
1436+ },
1437+ {
1438+ NO_IDX, "sdmux1", sdmux_parents, ARRAY_SIZE(sdmux_parents),
1439+ STM32F7_RCC_DCKCFGR2, 28, 1,
1440+ NO_GATE, 0,
1441+ 0
1442+ },
1443+ {
1444+ NO_IDX, "sdmux2", sdmux_parents, ARRAY_SIZE(sdmux_parents),
1445+ STM32F7_RCC_DCKCFGR2, 29, 1,
1446+ NO_GATE, 0,
1447+ 0
1448+ },
1449+ {
1450+ CLK_HDMI_CEC, "hdmi-cec",
1451+ hdmi_parents, ARRAY_SIZE(hdmi_parents),
1452+ STM32F7_RCC_DCKCFGR2, 26, 1,
1453+ NO_GATE, 0,
1454+ 0
1455+ },
1456+ {
1457+ CLK_SPDIF, "spdif-rx",
1458+ spdif_parent, ARRAY_SIZE(spdif_parent),
1459+ STM32F7_RCC_DCKCFGR2, 22, 3,
1460+ STM32F4_RCC_APB2ENR, 23,
1461+ CLK_SET_RATE_PARENT
1462+ },
1463+ {
1464+ CLK_USART1, "usart1",
1465+ uart_parents1, ARRAY_SIZE(uart_parents1),
1466+ STM32F7_RCC_DCKCFGR2, 0, 3,
1467+ STM32F4_RCC_APB2ENR, 4,
1468+ CLK_SET_RATE_PARENT,
1469+ },
1470+ {
1471+ CLK_USART2, "usart2",
1472+ uart_parents2, ARRAY_SIZE(uart_parents1),
1473+ STM32F7_RCC_DCKCFGR2, 2, 3,
1474+ STM32F4_RCC_APB1ENR, 17,
1475+ CLK_SET_RATE_PARENT,
1476+ },
1477+ {
1478+ CLK_USART3, "usart3",
1479+ uart_parents2, ARRAY_SIZE(uart_parents1),
1480+ STM32F7_RCC_DCKCFGR2, 4, 3,
1481+ STM32F4_RCC_APB1ENR, 18,
1482+ CLK_SET_RATE_PARENT,
1483+ },
1484+ {
1485+ CLK_UART4, "uart4",
1486+ uart_parents2, ARRAY_SIZE(uart_parents1),
1487+ STM32F7_RCC_DCKCFGR2, 6, 3,
1488+ STM32F4_RCC_APB1ENR, 19,
1489+ CLK_SET_RATE_PARENT,
1490+ },
1491+ {
1492+ CLK_UART5, "uart5",
1493+ uart_parents2, ARRAY_SIZE(uart_parents1),
1494+ STM32F7_RCC_DCKCFGR2, 8, 3,
1495+ STM32F4_RCC_APB1ENR, 20,
1496+ CLK_SET_RATE_PARENT,
1497+ },
1498+ {
1499+ CLK_USART6, "usart6",
1500+ uart_parents1, ARRAY_SIZE(uart_parents1),
1501+ STM32F7_RCC_DCKCFGR2, 10, 3,
1502+ STM32F4_RCC_APB2ENR, 5,
1503+ CLK_SET_RATE_PARENT,
1504+ },
1505+ {
1506+ CLK_UART7, "uart7",
1507+ uart_parents2, ARRAY_SIZE(uart_parents1),
1508+ STM32F7_RCC_DCKCFGR2, 12, 3,
1509+ STM32F4_RCC_APB1ENR, 30,
1510+ CLK_SET_RATE_PARENT,
1511+ },
1512+ {
1513+ CLK_UART8, "uart8",
1514+ uart_parents2, ARRAY_SIZE(uart_parents1),
1515+ STM32F7_RCC_DCKCFGR2, 14, 3,
1516+ STM32F4_RCC_APB1ENR, 31,
1517+ CLK_SET_RATE_PARENT,
1518+ },
1519+ {
1520+ CLK_I2C1, "i2c1",
1521+ i2c_parents, ARRAY_SIZE(i2c_parents),
1522+ STM32F7_RCC_DCKCFGR2, 16, 3,
1523+ STM32F4_RCC_APB1ENR, 21,
1524+ CLK_SET_RATE_PARENT,
1525+ },
1526+ {
1527+ CLK_I2C2, "i2c2",
1528+ i2c_parents, ARRAY_SIZE(i2c_parents),
1529+ STM32F7_RCC_DCKCFGR2, 18, 3,
1530+ STM32F4_RCC_APB1ENR, 22,
1531+ CLK_SET_RATE_PARENT,
1532+ },
1533+ {
1534+ CLK_I2C3, "i2c3",
1535+ i2c_parents, ARRAY_SIZE(i2c_parents),
1536+ STM32F7_RCC_DCKCFGR2, 20, 3,
1537+ STM32F4_RCC_APB1ENR, 23,
1538+ CLK_SET_RATE_PARENT,
1539+ },
1540+ {
1541+ CLK_I2C4, "i2c4",
1542+ i2c_parents, ARRAY_SIZE(i2c_parents),
1543+ STM32F7_RCC_DCKCFGR2, 22, 3,
1544+ STM32F4_RCC_APB1ENR, 24,
1545+ CLK_SET_RATE_PARENT,
1546+ },
1547+ {
1548+ CLK_LPTIMER, "lptim1",
1549+ lptim_parent, ARRAY_SIZE(lptim_parent),
1550+ STM32F7_RCC_DCKCFGR2, 24, 3,
1551+ STM32F4_RCC_APB1ENR, 9,
1552+ CLK_SET_RATE_PARENT
1553+ },
1554+ {
1555+ CLK_F769_DSI, "dsi",
1556+ dsi_parent, ARRAY_SIZE(dsi_parent),
1557+ STM32F7_RCC_DCKCFGR2, 0, 1,
1558+ STM32F4_RCC_APB2ENR, 27,
1559+ CLK_SET_RATE_PARENT
1560+ },
1561+ {
1562+ CLK_DFSDM1, "dfsdm1",
1563+ dfsdm1_src, ARRAY_SIZE(dfsdm1_src),
1564+ STM32F4_RCC_DCKCFGR, 25, 1,
1565+ STM32F4_RCC_APB2ENR, 29,
1566+ CLK_SET_RATE_PARENT
1567+ },
1568+ {
1569+ CLK_ADFSDM1, "adfsdm1",
1570+ adsfdm1_parent, ARRAY_SIZE(adsfdm1_parent),
1571+ STM32F4_RCC_DCKCFGR, 26, 1,
1572+ STM32F4_RCC_APB2ENR, 29,
1573+ CLK_SET_RATE_PARENT
1574+ },
1575+};
1576+
13161577 static const struct stm32f4_clk_data stm32f429_clk_data = {
13171578 .end_primary = END_PRIMARY_CLK,
13181579 .gates_data = stm32f429_gates,
@@ -1343,6 +1604,16 @@ static const struct stm32f4_clk_data stm32f746_clk_data = { · 24 unmodified lines
13431604 .aux_clk_num = ARRAY_SIZE(stm32f746_aux_clk),
13441605 };
13451606
1607+static const struct stm32f4_clk_data stm32f769_clk_data = {
1608+ .end_primary = END_PRIMARY_CLK_F7,
1609+ .gates_data = stm32f769_gates,
1610+ .gates_map = stm32f769_gate_map,
1611+ .gates_num = ARRAY_SIZE(stm32f769_gates),
1612+ .pll_data = stm32f469_pll,
1613+ .aux_clk = stm32f769_aux_clk,
1614+ .aux_clk_num = ARRAY_SIZE(stm32f769_aux_clk),
1615+};
1616+
13461617 static const struct of_device_id stm32f4_of_match[] = {
13471618 {
13481619 .compatible = "st,stm32f42xx-rcc",
@@ -1356,6 +1627,10 @@ static const struct of_device_id stm32f4_of_match[] = { · 7 unmodified lines
13561627 .compatible = "st,stm32f746-rcc",
13571628 .data = &stm32f746_clk_data
13581629 },
1630+ {
1631+ .compatible = "st,stm32f769-rcc",
1632+ .data = &stm32f769_clk_data
1633+ },
13591634 {}
13601635 };
13611636
@@ -1427,9 +1702,8 @@ static void __init stm32f4_rcc_init(struct device_node *np) · 65 unmodified lines
14271702 int n;
14281703 const struct of_device_id *match;
14291704 const struct stm32f4_clk_data *data;
1430− unsigned long pllcfgr;
1431− const char *pllsrc;
14321705 unsigned long pllm;
1706+ struct clk_hw *pll_src_hw;
14331707
14341708 base = of_iomap(np, 0);
14351709 if (!base) {
@@ -1460,21 +1734,33 @@ static void __init stm32f4_rcc_init(struct device_node *np) · 24 unmodified lines
14601734
14611735 hse_clk = of_clk_get_parent_name(np, 0);
14621736 dsi_parent[0] = hse_clk;
1737+ pllsrc_parent[1] = hse_clk;
14631738
14641739 i2s_in_clk = of_clk_get_parent_name(np, 1);
14651740
14661741 i2s_parents[1] = i2s_in_clk;
14671742 sai_parents[2] = i2s_in_clk;
14681743
1744+ if (of_device_is_compatible(np, "st,stm32f769-rcc")) {
1745+ clk_hw_register_gate(NULL, "dfsdm1_apb", "apb2_div", 0,
1746+ base + STM32F4_RCC_APB2ENR, 29,
1747+ CLK_IGNORE_UNUSED, &stm32f4_clk_lock);
1748+ dsi_parent[0] = pll_src;
1749+ sai_parents[3] = pll_src;
1750+ }
1751+
14691752 clks[CLK_HSI] = clk_hw_register_fixed_rate_with_accuracy(NULL, "hsi",
14701753 NULL, 0, 16000000, 160000);
14711754
1472− pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
1473− pllsrc = pllcfgr & BIT(22) ? hse_clk : "hsi";
1474− pllm = pllcfgr & 0x3f;
1755+ pll_src_hw = clk_hw_register_mux(NULL, pll_src, pllsrc_parent,
1756+ ARRAY_SIZE(pllsrc_parent), 0,
1757+ base + STM32F4_RCC_PLLCFGR, 22, 1, 0,
1758+ &stm32f4_clk_lock);
1759+
1760+ pllm = readl(base + STM32F4_RCC_PLLCFGR) & 0x3f;
14751761
1476− clk_hw_register_fixed_factor(NULL, "vco_in", pllsrc,
1477− 0, 1, pllm);
1762+ clk_hw_register_fixed_factor(NULL, "vco_in", pll_src,
1763+ 0, 1, pllm);
14781764
14791765 stm32f4_rcc_register_pll("vco_in", &data->pll_data[0],
14801766 &stm32f4_clk_lock);
@@ -1612,12 +1898,16 @@ static void __init stm32f4_rcc_init(struct device_node *np) · 131 unmodified lines
16121898 clks[aux_clk->idx] = hw;
16131899 }
16141900
1615− if (of_device_is_compatible(np, "st,stm32f746-rcc"))
1901+ if (of_device_is_compatible(np, "st,stm32f746-rcc")) {
16161902
16171903 clk_hw_register_fixed_factor(NULL, "hsi_div488", "hsi", 0,
16181904 1, 488);
16191905
1906+ clks[CLK_PLL_SRC] = pll_src_hw;
1907+ }
1908+
16201909 of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
1910+
16211911 return;
16221912 fail:
16231913 kfree(clks);
@@ -1626,3 +1916,4 @@ fail: · 2 unmodified lines
16261916 CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
16271917 CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
16281918 CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init);
1919+CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);
drivers/clk/clk-stm32mp1.c+3−0
@@ -1402,6 +1402,7 @@ enum { · 1401 unmodified lines
14021402 G_CRYP1,
14031403 G_HASH1,
14041404 G_BKPSRAM,
1405+ G_DDRPERFM,
14051406
14061407 G_LAST
14071408 };
@@ -1488,6 +1489,7 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = { · 80 unmodified lines
14881489 K_GATE(G_STGENRO, RCC_APB4ENSETR, 20, 0),
14891490 K_MGATE(G_USBPHY, RCC_APB4ENSETR, 16, 0),
14901491 K_GATE(G_IWDG2, RCC_APB4ENSETR, 15, 0),
1492+ K_GATE(G_DDRPERFM, RCC_APB4ENSETR, 8, 0),
14911493 K_MGATE(G_DSI, RCC_APB4ENSETR, 4, 0),
14921494 K_MGATE(G_LTDC, RCC_APB4ENSETR, 0, 0),
14931495
@@ -1899,6 +1901,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = { · 405 unmodified lines
18991901 PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1),
19001902 PCLK(USBH, "usbh", "ck_axi", 0, G_USBH),
19011903 PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP),
1904+ PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, G_DDRPERFM),
19021905
19031906 /* Kernel clocks */
19041907 KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
drivers/clk/davinci/pll.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 /*
33 * Clock driver for TI Davinci PSC controllers
44 *
drivers/clk/davinci/psc.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 /*
33 * Clock driver for TI Davinci PSC controllers
44 *
drivers/clk/qcom/clk-regmap-mux-div.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 /*
33 * Copyright (c) 2017, Linaro Limited
44 * Author: Georgi Djakov <georgi.djakov@linaro.org>
drivers/clk/renesas/rcar-gen2-cpg.h+2−2
@@ -1,5 +1,5 @@
1−/* SPDX-License-Identifier: GPL-2.0
2− *
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
33 * R-Car Gen2 Clock Pulse Generator
44 *
55 * Copyright (C) 2016 Cogent Embedded Inc.
drivers/clk/renesas/rcar-gen3-cpg.h+2−2
@@ -1,5 +1,5 @@
1−/* SPDX-License-Identifier: GPL-2.0
2− *
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
33 * R-Car Gen3 Clock Pulse Generator
44 *
55 * Copyright (C) 2015-2018 Glider bvba
drivers/clk/renesas/renesas-cpg-mssr.h+2−2
@@ -1,5 +1,5 @@
1−/* SPDX-License-Identifier: GPL-2.0
2− *
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
33 * Renesas Clock Pulse Generator / Module Standby and Software Reset
44 *
55 * Copyright (C) 2015 Glider bvba
drivers/clk/sifive/Kconfig+18−0
@@ -0,0 +1,18 @@
1+# SPDX-License-Identifier: GPL-2.0
2+
3+menuconfig CLK_SIFIVE
4+ bool "SiFive SoC driver support"
5+ help
6+ SoC drivers for SiFive Linux-capable SoCs.
7+
8+if CLK_SIFIVE
9+
10+config CLK_SIFIVE_FU540_PRCI
11+ bool "PRCI driver for SiFive FU540 SoCs"
12+ select CLK_ANALOGBITS_WRPLL_CLN28HPC
13+ help
14+ Supports the Power Reset Clock interface (PRCI) IP block found in
15+ FU540 SoCs. If this kernel is meant to run on a SiFive FU540 SoC,
16+ enable this driver.
17+
18+endif
drivers/clk/sifive/Makefile+1−0
@@ -0,0 +1 @@
1+obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI) += fu540-prci.o
drivers/clk/sifive/fu540-prci.c+626−0
@@ -0,0 +1,626 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Copyright (C) 2018-2019 SiFive, Inc.
4+ * Wesley Terpstra
5+ * Paul Walmsley
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License version 2 as
9+ * published by the Free Software Foundation.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * The FU540 PRCI implements clock and reset control for the SiFive
17+ * FU540-C000 chip. This driver assumes that it has sole control
18+ * over all PRCI resources.
19+ *
20+ * This driver is based on the PRCI driver written by Wesley Terpstra:
21+ * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60
22+ *
23+ * References:
24+ * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
25+ */
26+
27+#include <dt-bindings/clock/sifive-fu540-prci.h>
28+#include <linux/clkdev.h>
29+#include <linux/clk-provider.h>
30+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
31+#include <linux/delay.h>
32+#include <linux/err.h>
33+#include <linux/module.h>
34+#include <linux/of.h>
35+#include <linux/of_clk.h>
36+#include <linux/platform_device.h>
37+#include <linux/slab.h>
38+
39+/*
40+ * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
41+ * hfclk and rtcclk
42+ */
43+#define EXPECTED_CLK_PARENT_COUNT 2
44+
45+/*
46+ * Register offsets and bitmasks
47+ */
48+
49+/* COREPLLCFG0 */
50+#define PRCI_COREPLLCFG0_OFFSET 0x4
51+# define PRCI_COREPLLCFG0_DIVR_SHIFT 0
52+# define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
53+# define PRCI_COREPLLCFG0_DIVF_SHIFT 6
54+# define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
55+# define PRCI_COREPLLCFG0_DIVQ_SHIFT 15
56+# define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
57+# define PRCI_COREPLLCFG0_RANGE_SHIFT 18
58+# define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
59+# define PRCI_COREPLLCFG0_BYPASS_SHIFT 24
60+# define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
61+# define PRCI_COREPLLCFG0_FSE_SHIFT 25
62+# define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
63+# define PRCI_COREPLLCFG0_LOCK_SHIFT 31
64+# define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
65+
66+/* DDRPLLCFG0 */
67+#define PRCI_DDRPLLCFG0_OFFSET 0xc
68+# define PRCI_DDRPLLCFG0_DIVR_SHIFT 0
69+# define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
70+# define PRCI_DDRPLLCFG0_DIVF_SHIFT 6
71+# define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
72+# define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15
73+# define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
74+# define PRCI_DDRPLLCFG0_RANGE_SHIFT 18
75+# define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
76+# define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24
77+# define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
78+# define PRCI_DDRPLLCFG0_FSE_SHIFT 25
79+# define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
80+# define PRCI_DDRPLLCFG0_LOCK_SHIFT 31
81+# define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
82+
83+/* DDRPLLCFG1 */
84+#define PRCI_DDRPLLCFG1_OFFSET 0x10
85+# define PRCI_DDRPLLCFG1_CKE_SHIFT 24
86+# define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
87+
88+/* GEMGXLPLLCFG0 */
89+#define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c
90+# define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0
91+# define PRCI_GEMGXLPLLCFG0_DIVR_MASK (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
92+# define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6
93+# define PRCI_GEMGXLPLLCFG0_DIVF_MASK (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
94+# define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15
95+# define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
96+# define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18
97+# define PRCI_GEMGXLPLLCFG0_RANGE_MASK (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
98+# define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24
99+# define PRCI_GEMGXLPLLCFG0_BYPASS_MASK (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
100+# define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25
101+# define PRCI_GEMGXLPLLCFG0_FSE_MASK (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
102+# define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31
103+# define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
104+
105+/* GEMGXLPLLCFG1 */
106+#define PRCI_GEMGXLPLLCFG1_OFFSET 0x20
107+# define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 24
108+# define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
109+
110+/* CORECLKSEL */
111+#define PRCI_CORECLKSEL_OFFSET 0x24
112+# define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0
113+# define PRCI_CORECLKSEL_CORECLKSEL_MASK (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
114+
115+/* DEVICESRESETREG */
116+#define PRCI_DEVICESRESETREG_OFFSET 0x28
117+# define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT 0
118+# define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
119+# define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT 1
120+# define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
121+# define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT 2
122+# define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
123+# define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT 3
124+# define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
125+# define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT 5
126+# define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
127+
128+/* CLKMUXSTATUSREG */
129+#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c
130+# define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1
131+# define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
132+
133+/*
134+ * Private structures
135+ */
136+
137+/**
138+ * struct __prci_data - per-device-instance data
139+ * @va: base virtual address of the PRCI IP block
140+ * @hw_clks: encapsulates struct clk_hw records
141+ *
142+ * PRCI per-device instance data
143+ */
144+struct __prci_data {
145+ void __iomem *va;
146+ struct clk_hw_onecell_data hw_clks;
147+};
148+
149+/**
150+ * struct __prci_wrpll_data - WRPLL configuration and integration data
151+ * @c: WRPLL current configuration record
152+ * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
153+ * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
154+ * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
155+ *
156+ * @enable_bypass and @disable_bypass are used for WRPLL instances
157+ * that contain a separate external glitchless clock mux downstream
158+ * from the PLL. The WRPLL internal bypass mux is not glitchless.
159+ */
160+struct __prci_wrpll_data {
161+ struct wrpll_cfg c;
162+ void (*enable_bypass)(struct __prci_data *pd);
163+ void (*disable_bypass)(struct __prci_data *pd);
164+ u8 cfg0_offs;
165+};
166+
167+/**
168+ * struct __prci_clock - describes a clock device managed by PRCI
169+ * @name: user-readable clock name string - should match the manual
170+ * @parent_name: parent name for this clock
171+ * @ops: struct clk_ops for the Linux clock framework to use for control
172+ * @hw: Linux-private clock data
173+ * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
174+ * @pd: PRCI-specific data associated with this clock (if not NULL)
175+ *
176+ * PRCI clock data. Used by the PRCI driver to register PRCI-provided
177+ * clocks to the Linux clock infrastructure.
178+ */
179+struct __prci_clock {
180+ const char *name;
181+ const char *parent_name;
182+ const struct clk_ops *ops;
183+ struct clk_hw hw;
184+ struct __prci_wrpll_data *pwd;
185+ struct __prci_data *pd;
186+};
187+
188+#define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
189+
190+/*
191+ * Private functions
192+ */
193+
194+/**
195+ * __prci_readl() - read from a PRCI register
196+ * @pd: PRCI context
197+ * @offs: register offset to read from (in bytes, from PRCI base address)
198+ *
199+ * Read the register located at offset @offs from the base virtual
200+ * address of the PRCI register target described by @pd, and return
201+ * the value to the caller.
202+ *
203+ * Context: Any context.
204+ *
205+ * Return: the contents of the register described by @pd and @offs.
206+ */
207+static u32 __prci_readl(struct __prci_data *pd, u32 offs)
208+{
209+ return readl_relaxed(pd->va + offs);
210+}
211+
212+static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
213+{
214+ writel_relaxed(v, pd->va + offs);
215+}
216+
217+/* WRPLL-related private functions */
218+
219+/**
220+ * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
221+ * @c: ptr to a struct wrpll_cfg record to write config into
222+ * @r: value read from the PRCI PLL configuration register
223+ *
224+ * Given a value @r read from an FU540 PRCI PLL configuration register,
225+ * split it into fields and populate it into the WRPLL configuration record
226+ * pointed to by @c.
227+ *
228+ * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
229+ * have the same register layout.
230+ *
231+ * Context: Any context.
232+ */
233+static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
234+{
235+ u32 v;
236+
237+ v = r & PRCI_COREPLLCFG0_DIVR_MASK;
238+ v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
239+ c->divr = v;
240+
241+ v = r & PRCI_COREPLLCFG0_DIVF_MASK;
242+ v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
243+ c->divf = v;
244+
245+ v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
246+ v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
247+ c->divq = v;
248+
249+ v = r & PRCI_COREPLLCFG0_RANGE_MASK;
250+ v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
251+ c->range = v;
252+
253+ c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
254+ WRPLL_FLAGS_EXT_FEEDBACK_MASK);
255+
256+ /* external feedback mode not supported */
257+ c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
258+}
259+
260+/**
261+ * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
262+ * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
263+ *
264+ * Using a set of WRPLL configuration values pointed to by @c,
265+ * assemble a PRCI PLL configuration register value, and return it to
266+ * the caller.
267+ *
268+ * Context: Any context. Caller must ensure that the contents of the
269+ * record pointed to by @c do not change during the execution
270+ * of this function.
271+ *
272+ * Returns: a value suitable for writing into a PRCI PLL configuration
273+ * register
274+ */
275+static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
276+{
277+ u32 r = 0;
278+
279+ r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
280+ r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
281+ r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
282+ r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
283+
284+ /* external feedback mode not supported */
285+ r |= PRCI_COREPLLCFG0_FSE_MASK;
286+
287+ return r;
288+}
289+
290+/**
291+ * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI
292+ * @pd: PRCI context
293+ * @pwd: PRCI WRPLL metadata
294+ *
295+ * Read the current configuration of the PLL identified by @pwd from
296+ * the PRCI identified by @pd, and store it into the local configuration
297+ * cache in @pwd.
298+ *
299+ * Context: Any context. Caller must prevent the records pointed to by
300+ * @pd and @pwd from changing during execution.
301+ */
302+static void __prci_wrpll_read_cfg(struct __prci_data *pd,
303+ struct __prci_wrpll_data *pwd)
304+{
305+ __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
306+}
307+
308+/**
309+ * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI
310+ * @pd: PRCI context
311+ * @pwd: PRCI WRPLL metadata
312+ * @c: WRPLL configuration record to write
313+ *
314+ * Write the WRPLL configuration described by @c into the WRPLL
315+ * configuration register identified by @pwd in the PRCI instance
316+ * described by @c. Make a cached copy of the WRPLL's current
317+ * configuration so it can be used by other code.
318+ *
319+ * Context: Any context. Caller must prevent the records pointed to by
320+ * @pd and @pwd from changing during execution.
321+ */
322+static void __prci_wrpll_write_cfg(struct __prci_data *pd,
323+ struct __prci_wrpll_data *pwd,
324+ struct wrpll_cfg *c)
325+{
326+ __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
327+
328+ memcpy(&pwd->c, c, sizeof(*c));
329+}
330+
331+/* Core clock mux control */
332+
333+/**
334+ * __prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
335+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
336+ *
337+ * Switch the CORECLK mux to the HFCLK input source; return once complete.
338+ *
339+ * Context: Any context. Caller must prevent concurrent changes to the
340+ * PRCI_CORECLKSEL_OFFSET register.
341+ */
342+static void __prci_coreclksel_use_hfclk(struct __prci_data *pd)
343+{
344+ u32 r;
345+
346+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
347+ r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
348+ __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
349+
350+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
351+}
352+
353+/**
354+ * __prci_coreclksel_use_corepll() - switch the CORECLK mux to output COREPLL
355+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
356+ *
357+ * Switch the CORECLK mux to the PLL output clock; return once complete.
358+ *
359+ * Context: Any context. Caller must prevent concurrent changes to the
360+ * PRCI_CORECLKSEL_OFFSET register.
361+ */
362+static void __prci_coreclksel_use_corepll(struct __prci_data *pd)
363+{
364+ u32 r;
365+
366+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
367+ r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
368+ __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
369+
370+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
371+}
372+
373+/*
374+ * Linux clock framework integration
375+ *
376+ * See the Linux clock framework documentation for more information on
377+ * these functions.
378+ */
379+
380+static unsigned long sifive_fu540_prci_wrpll_recalc_rate(struct clk_hw *hw,
381+ unsigned long parent_rate)
382+{
383+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
384+ struct __prci_wrpll_data *pwd = pc->pwd;
385+
386+ return wrpll_calc_output_rate(&pwd->c, parent_rate);
387+}
388+
389+static long sifive_fu540_prci_wrpll_round_rate(struct clk_hw *hw,
390+ unsigned long rate,
391+ unsigned long *parent_rate)
392+{
393+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
394+ struct __prci_wrpll_data *pwd = pc->pwd;
395+ struct wrpll_cfg c;
396+
397+ memcpy(&c, &pwd->c, sizeof(c));
398+
399+ wrpll_configure_for_rate(&c, rate, *parent_rate);
400+
401+ return wrpll_calc_output_rate(&c, *parent_rate);
402+}
403+
404+static int sifive_fu540_prci_wrpll_set_rate(struct clk_hw *hw,
405+ unsigned long rate,
406+ unsigned long parent_rate)
407+{
408+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
409+ struct __prci_wrpll_data *pwd = pc->pwd;
410+ struct __prci_data *pd = pc->pd;
411+ int r;
412+
413+ r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
414+ if (r)
415+ return r;
416+
417+ if (pwd->enable_bypass)
418+ pwd->enable_bypass(pd);
419+
420+ __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
421+
422+ udelay(wrpll_calc_max_lock_us(&pwd->c));
423+
424+ if (pwd->disable_bypass)
425+ pwd->disable_bypass(pd);
426+
427+ return 0;
428+}
429+
430+static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
431+ .set_rate = sifive_fu540_prci_wrpll_set_rate,
432+ .round_rate = sifive_fu540_prci_wrpll_round_rate,
433+ .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
434+};
435+
436+static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
437+ .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
438+};
439+
440+/* TLCLKSEL clock integration */
441+
442+static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(struct clk_hw *hw,
443+ unsigned long parent_rate)
444+{
445+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
446+ struct __prci_data *pd = pc->pd;
447+ u32 v;
448+ u8 div;
449+
450+ v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
451+ v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
452+ div = v ? 1 : 2;
453+
454+ return div_u64(parent_rate, div);
455+}
456+
457+static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
458+ .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
459+};
460+
461+/*
462+ * PRCI integration data for each WRPLL instance
463+ */
464+
465+static struct __prci_wrpll_data __prci_corepll_data = {
466+ .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
467+ .enable_bypass = __prci_coreclksel_use_hfclk,
468+ .disable_bypass = __prci_coreclksel_use_corepll,
469+};
470+
471+static struct __prci_wrpll_data __prci_ddrpll_data = {
472+ .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
473+};
474+
475+static struct __prci_wrpll_data __prci_gemgxlpll_data = {
476+ .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
477+};
478+
479+/*
480+ * List of clock controls provided by the PRCI
481+ */
482+
483+static struct __prci_clock __prci_init_clocks[] = {
484+ [PRCI_CLK_COREPLL] = {
485+ .name = "corepll",
486+ .parent_name = "hfclk",
487+ .ops = &sifive_fu540_prci_wrpll_clk_ops,
488+ .pwd = &__prci_corepll_data,
489+ },
490+ [PRCI_CLK_DDRPLL] = {
491+ .name = "ddrpll",
492+ .parent_name = "hfclk",
493+ .ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
494+ .pwd = &__prci_ddrpll_data,
495+ },
496+ [PRCI_CLK_GEMGXLPLL] = {
497+ .name = "gemgxlpll",
498+ .parent_name = "hfclk",
499+ .ops = &sifive_fu540_prci_wrpll_clk_ops,
500+ .pwd = &__prci_gemgxlpll_data,
501+ },
502+ [PRCI_CLK_TLCLK] = {
503+ .name = "tlclk",
504+ .parent_name = "corepll",
505+ .ops = &sifive_fu540_prci_tlclksel_clk_ops,
506+ },
507+};
508+
509+/**
510+ * __prci_register_clocks() - register clock controls in the PRCI with Linux
511+ * @dev: Linux struct device *
512+ *
513+ * Register the list of clock controls described in __prci_init_plls[] with
514+ * the Linux clock framework.
515+ *
516+ * Return: 0 upon success or a negative error code upon failure.
517+ */
518+static int __prci_register_clocks(struct device *dev, struct __prci_data *pd)
519+{
520+ struct clk_init_data init = { };
521+ struct __prci_clock *pic;
522+ int parent_count, i, r;
523+
524+ parent_count = of_clk_get_parent_count(dev->of_node);
525+ if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
526+ dev_err(dev, "expected only two parent clocks, found %d\n",
527+ parent_count);
528+ return -EINVAL;
529+ }
530+
531+ /* Register PLLs */
532+ for (i = 0; i < ARRAY_SIZE(__prci_init_clocks); ++i) {
533+ pic = &__prci_init_clocks[i];
534+
535+ init.name = pic->name;
536+ init.parent_names = &pic->parent_name;
537+ init.num_parents = 1;
538+ init.ops = pic->ops;
539+ pic->hw.init = &init;
540+
541+ pic->pd = pd;
542+
543+ if (pic->pwd)
544+ __prci_wrpll_read_cfg(pd, pic->pwd);
545+
546+ r = devm_clk_hw_register(dev, &pic->hw);
547+ if (r) {
548+ dev_warn(dev, "Failed to register clock %s: %d\n",
549+ init.name, r);
550+ return r;
551+ }
552+
553+ r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
554+ if (r) {
555+ dev_warn(dev, "Failed to register clkdev for %s: %d\n",
556+ init.name, r);
557+ return r;
558+ }
559+
560+ pd->hw_clks.hws[i] = &pic->hw;
561+ }
562+
563+ pd->hw_clks.num = i;
564+
565+ r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
566+ &pd->hw_clks);
567+ if (r) {
568+ dev_err(dev, "could not add hw_provider: %d\n", r);
569+ return r;
570+ }
571+
572+ return 0;
573+}
574+
575+/*
576+ * Linux device model integration
577+ *
578+ * See the Linux device model documentation for more information about
579+ * these functions.
580+ */
581+static int sifive_fu540_prci_probe(struct platform_device *pdev)
582+{
583+ struct device *dev = &pdev->dev;
584+ struct resource *res;
585+ struct __prci_data *pd;
586+ int r;
587+
588+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
589+ if (!pd)
590+ return -ENOMEM;
591+
592+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
593+ pd->va = devm_ioremap_resource(dev, res);
594+ if (IS_ERR(pd->va))
595+ return PTR_ERR(pd->va);
596+
597+ r = __prci_register_clocks(dev, pd);
598+ if (r) {
599+ dev_err(dev, "could not register clocks: %d\n", r);
600+ return r;
601+ }
602+
603+ dev_dbg(dev, "SiFive FU540 PRCI probed\n");
604+
605+ return 0;
606+}
607+
608+static const struct of_device_id sifive_fu540_prci_of_match[] = {
609+ { .compatible = "sifive,fu540-c000-prci", },
610+ {}
611+};
612+MODULE_DEVICE_TABLE(of, sifive_fu540_prci_of_match);
613+
614+static struct platform_driver sifive_fu540_prci_driver = {
615+ .driver = {
616+ .name = "sifive-fu540-prci",
617+ .of_match_table = sifive_fu540_prci_of_match,
618+ },
619+ .probe = sifive_fu540_prci_probe,
620+};
621+
622+static int __init sifive_fu540_prci_init(void)
623+{
624+ return platform_driver_register(&sifive_fu540_prci_driver);
625+}
626+core_initcall(sifive_fu540_prci_init);
drivers/clk/sprd/common.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 //
33 // Spreadtrum clock infrastructure
44 //
drivers/clk/sprd/composite.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 //
33 // Spreadtrum composite clock driver
44 //
drivers/clk/sprd/div.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 //
33 // Spreadtrum divider clock driver
44 //
drivers/clk/sprd/gate.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 //
33 // Spreadtrum gate clock driver
44 //
drivers/clk/sprd/mux.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 //
33 // Spreadtrum multiplexer clock driver
44 //
drivers/clk/sprd/pll.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 //
33 // Spreadtrum pll clock driver
44 //
drivers/clk/sunxi-ng/ccu-sun50i-h6.h+1−1
@@ -1,4 +1,4 @@
1−// SPDX-License-Identifier: GPL-2.0
1+/* SPDX-License-Identifier: GPL-2.0 */
22 /*
33 * Copyright 2016 Icenowy Zheng <icenowy@aosc.io>
44 */
drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h+2−2
@@ -1,5 +1,5 @@
1−/* SPDX-License-Identifier: GPL-2.0+
2− *
1+/* SPDX-License-Identifier: GPL-2.0+ */
2+/*
33 * Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
44 *
55 */
drivers/clk/tegra/clk-divider.c+2−1
@@ -175,6 +175,7 @@ struct clk *tegra_clk_register_mc(const char *name, const char *parent_name, · 174 unmodified lines
175175 void __iomem *reg, spinlock_t *lock)
176176 {
177177 return clk_register_divider_table(NULL, name, parent_name,
178− CLK_IS_CRITICAL, reg, 16, 1, 0,
178+ CLK_IS_CRITICAL,
179+ reg, 16, 1, CLK_DIVIDER_READ_ONLY,
179180 mc_div_table, lock);
180181 }
drivers/clk/tegra/clk-emc.c+35−22
@@ -121,18 +121,28 @@ static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) · 120 unmodified lines
121121 struct tegra_clk_emc *tegra;
122122 u8 ram_code = tegra_read_ram_code();
123123 struct emc_timing *timing = NULL;
124− int i;
124+ int i, k, t;
125125
126126 tegra = container_of(hw, struct tegra_clk_emc, hw);
127127
128− for (i = 0; i < tegra->num_timings; i++) {
129− if (tegra->timings[i].ram_code != ram_code)
130− continue;
128+ for (k = 0; k < tegra->num_timings; k++) {
129+ if (tegra->timings[k].ram_code == ram_code)
130+ break;
131+ }
132+
133+ for (t = k; t < tegra->num_timings; t++) {
134+ if (tegra->timings[t].ram_code != ram_code)
135+ break;
136+ }
131137
138+ for (i = k; i < t; i++) {
132139 timing = tegra->timings + i;
133140
141+ if (timing->rate < req->rate && i != t - 1)
142+ continue;
143+
134144 if (timing->rate > req->max_rate) {
135− i = max(i, 1);
145+ i = max(i, k + 1);
136146 req->rate = tegra->timings[i - 1].rate;
137147 return 0;
138148 }
@@ -140,10 +150,8 @@ static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) · 1 unmodified line
140150 if (timing->rate < req->min_rate)
141151 continue;
142152
143− if (timing->rate >= req->rate) {
144− req->rate = timing->rate;
145− return 0;
146− }
153+ req->rate = timing->rate;
154+ return 0;
147155 }
148156
149157 if (timing) {
@@ -214,7 +222,10 @@ static int emc_set_timing(struct tegra_clk_emc *tegra, · 64 unmodified lines
214222
215223 if (emc_get_parent(&tegra->hw) == timing->parent_index &&
216224 clk_get_rate(timing->parent) != timing->parent_rate) {
217− BUG();
225+ WARN_ONCE(1, "parent %s rate mismatch %lu %lu\n",
226+ __clk_get_name(timing->parent),
227+ clk_get_rate(timing->parent),
228+ timing->parent_rate);
218229 return -EINVAL;
219230 }
220231
@@ -282,7 +293,7 @@ static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra, · 61 unmodified lines
282293 for (i = timing_index+1; i < tegra->num_timings; i++) {
283294 timing = tegra->timings + i;
284295 if (timing->ram_code != ram_code)
285− continue;
296+ break;
286297
287298 if (emc_parent_clk_sources[timing->parent_index] !=
288299 emc_parent_clk_sources[
@@ -293,7 +304,7 @@ static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra, · 4 unmodified lines
293304 for (i = timing_index-1; i >= 0; --i) {
294305 timing = tegra->timings + i;
295306 if (timing->ram_code != ram_code)
296− continue;
307+ break;
297308
298309 if (emc_parent_clk_sources[timing->parent_index] !=
299310 emc_parent_clk_sources[
@@ -433,19 +444,23 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, · 133 unmodified lines
433444 struct device_node *node,
434445 u32 ram_code)
435446 {
447+ struct emc_timing *timings_ptr;
436448 struct device_node *child;
437449 int child_count = of_get_child_count(node);
438450 int i = 0, err;
451+ size_t size;
439452
440− tegra->timings = kcalloc(child_count, sizeof(struct emc_timing),
441− GFP_KERNEL);
453+ size = (tegra->num_timings + child_count) * sizeof(struct emc_timing);
454+
455+ tegra->timings = krealloc(tegra->timings, size, GFP_KERNEL);
442456 if (!tegra->timings)
443457 return -ENOMEM;
444458
445− tegra->num_timings = child_count;
459+ timings_ptr = tegra->timings + tegra->num_timings;
460+ tegra->num_timings += child_count;
446461
447462 for_each_child_of_node(node, child) {
448− struct emc_timing *timing = tegra->timings + (i++);
463+ struct emc_timing *timing = timings_ptr + (i++);
449464
450465 err = load_one_timing_from_dt(tegra, timing, child);
451466 if (err) {
@@ -456,7 +471,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, · 4 unmodified lines
456471 timing->ram_code = ram_code;
457472 }
458473
459− sort(tegra->timings, tegra->num_timings, sizeof(struct emc_timing),
474+ sort(timings_ptr, child_count, sizeof(struct emc_timing),
460475 cmp_timings, NULL);
461476
462477 return 0;
@@ -499,10 +514,10 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, · 36 unmodified lines
499514 * fuses until the apbmisc driver is loaded.
500515 */
501516 err = load_timings_from_dt(tegra, node, node_ram_code);
502− of_node_put(node);
503− if (err)
517+ if (err) {
518+ of_node_put(node);
504519 return ERR_PTR(err);
505− break;
520+ }
506521 }
507522
508523 if (tegra->num_timings == 0)
@@ -532,7 +547,5 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, · 23 unmodified lines
532547 /* Allow debugging tools to see the EMC clock */
533548 clk_register_clkdev(clk, "emc", "tegra-clk-debug");
534549
535− clk_prepare_enable(clk);
536−
537550 return clk;
538551 };
drivers/clk/tegra/clk-pll.c+39−15
@@ -444,6 +444,9 @@ static int clk_pll_enable(struct clk_hw *hw) · 443 unmodified lines
444444 unsigned long flags = 0;
445445 int ret;
446446
447+ if (clk_pll_is_enabled(hw))
448+ return 0;
449+
447450 if (pll->lock)
448451 spin_lock_irqsave(pll->lock, flags);
449452
@@ -663,8 +666,8 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, · 213 unmodified lines
663666 pll_override_writel(val, params->pmc_divp_reg, pll);
664667
665668 val = pll_override_readl(params->pmc_divnm_reg, pll);
666− val &= ~(divm_mask(pll) << div_nmp->override_divm_shift) |
667− ~(divn_mask(pll) << div_nmp->override_divn_shift);
669+ val &= ~((divm_mask(pll) << div_nmp->override_divm_shift) |
670+ (divn_mask(pll) << div_nmp->override_divn_shift));
668671 val |= (cfg->m << div_nmp->override_divm_shift) |
669672 (cfg->n << div_nmp->override_divn_shift);
670673 pll_override_writel(val, params->pmc_divnm_reg, pll);
@@ -940,11 +943,16 @@ static int clk_plle_training(struct tegra_clk_pll *pll) · 269 unmodified lines
940943 static int clk_plle_enable(struct clk_hw *hw)
941944 {
942945 struct tegra_clk_pll *pll = to_clk_pll(hw);
943− unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
944946 struct tegra_clk_pll_freq_table sel;
947+ unsigned long input_rate;
945948 u32 val;
946949 int err;
947950
951+ if (clk_pll_is_enabled(hw))
952+ return 0;
953+
954+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
955+
948956 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
949957 return -EINVAL;
950958
@@ -1355,6 +1363,9 @@ static int clk_pllc_enable(struct clk_hw *hw) · 404 unmodified lines
13551363 int ret;
13561364 unsigned long flags = 0;
13571365
1366+ if (clk_pll_is_enabled(hw))
1367+ return 0;
1368+
13581369 if (pll->lock)
13591370 spin_lock_irqsave(pll->lock, flags);
13601371
@@ -1567,7 +1578,12 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) · 206 unmodified lines
15671578 u32 val;
15681579 int ret;
15691580 unsigned long flags = 0;
1570− unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
1581+ unsigned long input_rate;
1582+
1583+ if (clk_pll_is_enabled(hw))
1584+ return 0;
1585+
1586+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
15711587
15721588 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
15731589 return -EINVAL;
@@ -1704,6 +1720,9 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw) · 130 unmodified lines
17041720 return -EINVAL;
17051721 }
17061722
1723+ if (clk_pll_is_enabled(hw))
1724+ return 0;
1725+
17071726 input_rate = clk_hw_get_rate(__clk_get_hw(osc));
17081727
17091728 if (pll->lock)
@@ -2379,6 +2398,16 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, · 669 unmodified lines
23792398 return clk;
23802399 }
23812400
2401+static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
2402+{
2403+ struct tegra_clk_pll *pll = to_clk_pll(hw);
2404+ u32 val;
2405+
2406+ val = pll_readl_base(pll);
2407+
2408+ return val & PLLE_BASE_ENABLE ? 1 : 0;
2409+}
2410+
23822411 static int clk_plle_tegra210_enable(struct clk_hw *hw)
23832412 {
23842413 struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -2386,7 +2415,12 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) · 1 unmodified line
23862415 u32 val;
23872416 int ret = 0;
23882417 unsigned long flags = 0;
2389− unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
2418+ unsigned long input_rate;
2419+
2420+ if (clk_plle_tegra210_is_enabled(hw))
2421+ return 0;
2422+
2423+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
23902424
23912425 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
23922426 return -EINVAL;
@@ -2497,16 +2531,6 @@ out: · 104 unmodified lines
24972531 spin_unlock_irqrestore(pll->lock, flags);
24982532 }
24992533
2500−static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
2501−{
2502− struct tegra_clk_pll *pll = to_clk_pll(hw);
2503− u32 val;
2504−
2505− val = pll_readl_base(pll);
2506−
2507− return val & PLLE_BASE_ENABLE ? 1 : 0;
2508−}
2509−
25102534 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
25112535 .is_enabled = clk_plle_tegra210_is_enabled,
25122536 .enable = clk_plle_tegra210_enable,
drivers/clk/tegra/clk-tegra124.c+1−2
@@ -413,7 +413,6 @@ static struct tegra_clk_pll_params pll_m_params = { · 412 unmodified lines
413413 .base_reg = PLLM_BASE,
414414 .misc_reg = PLLM_MISC,
415415 .lock_mask = PLL_BASE_LOCK,
416− .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
417416 .lock_delay = 300,
418417 .max_p = 5,
419418 .pdiv_tohw = pllm_p,
@@ -421,7 +420,7 @@ static struct tegra_clk_pll_params pll_m_params = { · 1 unmodified line
421420 .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
422421 .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
423422 .freq_table = pll_m_freq_table,
424− .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
423+ .flags = TEGRA_PLL_USE_LOCK,
425424 };
426425
427426 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
include/dt-bindings/clock/stm32fx-clock.h+5−2
@@ -54,7 +54,10 @@ · 53 unmodified lines
5454 #define CLK_I2C3 28
5555 #define CLK_I2C4 29
5656 #define CLK_LPTIMER 30
57−
58−#define END_PRIMARY_CLK_F7 31
57+#define CLK_PLL_SRC 31
58+#define CLK_DFSDM1 32
59+#define CLK_ADFSDM1 33
60+#define CLK_F769_DSI 34
61+#define END_PRIMARY_CLK_F7 35
5962
6063 #endif
include/linux/clk/analogbits-wrpll-cln28hpc.h+79−0
@@ -0,0 +1,79 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Copyright (C) 2018-2019 SiFive, Inc.
4+ * Wesley Terpstra
5+ * Paul Walmsley
6+ */
7+
8+#ifndef __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
9+#define __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
10+
11+#include <linux/types.h>
12+
13+/* DIVQ_VALUES: number of valid DIVQ values */
14+#define DIVQ_VALUES 6
15+
16+/*
17+ * Bit definitions for struct wrpll_cfg.flags
18+ *
19+ * WRPLL_FLAGS_BYPASS_FLAG: if set, the PLL is either in bypass, or should be
20+ * programmed to enter bypass
21+ * WRPLL_FLAGS_RESET_FLAG: if set, the PLL is in reset
22+ * WRPLL_FLAGS_INT_FEEDBACK_FLAG: if set, the PLL is configured for internal
23+ * feedback mode
24+ * WRPLL_FLAGS_EXT_FEEDBACK_FLAG: if set, the PLL is configured for external
25+ * feedback mode (not yet supported by this driver)
26+ */
27+#define WRPLL_FLAGS_BYPASS_SHIFT 0
28+#define WRPLL_FLAGS_BYPASS_MASK BIT(WRPLL_FLAGS_BYPASS_SHIFT)
29+#define WRPLL_FLAGS_RESET_SHIFT 1
30+#define WRPLL_FLAGS_RESET_MASK BIT(WRPLL_FLAGS_RESET_SHIFT)
31+#define WRPLL_FLAGS_INT_FEEDBACK_SHIFT 2
32+#define WRPLL_FLAGS_INT_FEEDBACK_MASK BIT(WRPLL_FLAGS_INT_FEEDBACK_SHIFT)
33+#define WRPLL_FLAGS_EXT_FEEDBACK_SHIFT 3
34+#define WRPLL_FLAGS_EXT_FEEDBACK_MASK BIT(WRPLL_FLAGS_EXT_FEEDBACK_SHIFT)
35+
36+/**
37+ * struct wrpll_cfg - WRPLL configuration values
38+ * @divr: reference divider value (6 bits), as presented to the PLL signals
39+ * @divf: feedback divider value (9 bits), as presented to the PLL signals
40+ * @divq: output divider value (3 bits), as presented to the PLL signals
41+ * @flags: PLL configuration flags. See above for more information
42+ * @range: PLL loop filter range. See below for more information
43+ * @output_rate_cache: cached output rates, swept across DIVQ
44+ * @parent_rate: PLL refclk rate for which values are valid
45+ * @max_r: maximum possible R divider value, given @parent_rate
46+ * @init_r: initial R divider value to start the search from
47+ *
48+ * @divr, @divq, @divq, @range represent what the PLL expects to see
49+ * on its input signals. Thus @divr and @divf are the actual divisors
50+ * minus one. @divq is a power-of-two divider; for example, 1 =
51+ * divide-by-2 and 6 = divide-by-64. 0 is an invalid @divq value.
52+ *
53+ * When initially passing a struct wrpll_cfg record, the
54+ * record should be zero-initialized with the exception of the @flags
55+ * field. The only flag bits that need to be set are either
56+ * WRPLL_FLAGS_INT_FEEDBACK or WRPLL_FLAGS_EXT_FEEDBACK.
57+ */
58+struct wrpll_cfg {
59+ u8 divr;
60+ u8 divq;
61+ u8 range;
62+ u8 flags;
63+ u16 divf;
64+/* private: */
65+ u32 output_rate_cache[DIVQ_VALUES];
66+ unsigned long parent_rate;
67+ u8 max_r;
68+ u8 init_r;
69+};
70+
71+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
72+ unsigned long parent_rate);
73+
74+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c);
75+
76+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
77+ unsigned long parent_rate);
78+
79+#endif /* __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H */
include/linux/clk/at91_pmc.h+3−9
@@ -74,6 +74,8 @@ · 73 unmodified lines
7474 #define AT91_PMC_USBDIV_4 (2 << 28)
7575 #define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */
7676
77+#define AT91_PMC_CPU_CKR 0x28 /* CPU Clock Register */
78+
7779 #define AT91_PMC_MCKR 0x30 /* Master Clock Register */
7880 #define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */
7981 #define AT91_PMC_CSS_SLOW (0 << 0)
@@ -187,16 +189,8 @@ · 107 unmodified lines
187189
188190 #define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9 and SAMA5] */
189191 #define AT91_PMC_PCR_PID_MASK 0x3f
190−#define AT91_PMC_PCR_GCKCSS_OFFSET 8
191−#define AT91_PMC_PCR_GCKCSS_MASK (0x7 << AT91_PMC_PCR_GCKCSS_OFFSET)
192−#define AT91_PMC_PCR_GCKCSS(n) ((n) << AT91_PMC_PCR_GCKCSS_OFFSET) /* GCK Clock Source Selection */
193192 #define AT91_PMC_PCR_CMD (0x1 << 12) /* Command (read=0, write=1) */
194−#define AT91_PMC_PCR_DIV_OFFSET 16
195−#define AT91_PMC_PCR_DIV_MASK (0x3 << AT91_PMC_PCR_DIV_OFFSET)
196−#define AT91_PMC_PCR_DIV(n) ((n) << AT91_PMC_PCR_DIV_OFFSET) /* Divisor Value */
197−#define AT91_PMC_PCR_GCKDIV_OFFSET 20
198−#define AT91_PMC_PCR_GCKDIV_MASK (0xff << AT91_PMC_PCR_GCKDIV_OFFSET)
199−#define AT91_PMC_PCR_GCKDIV(n) ((n) << AT91_PMC_PCR_GCKDIV_OFFSET) /* Generated Clock Divisor Value */
193+#define AT91_PMC_PCR_GCKDIV_MASK GENMASK(27, 20)
200194 #define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */
201195 #define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */
202196

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t