Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+2432 -267
+14 -19
Documentation/devicetree/bindings/clock/at91-clock.txt
··· 8 8 9 9 Required properties: 10 10 - compatible : shall be one of the following: 11 - "atmel,at91sam9x5-sckc" or 11 + "atmel,at91sam9x5-sckc", 12 + "atmel,sama5d3-sckc" or 12 13 "atmel,sama5d4-sckc": 13 14 at91 SCKC (Slow Clock Controller) 14 - This node contains the slow clock definitions. 15 + - #clock-cells : shall be 0. 16 + - clocks : shall be the input parent clock phandle for the clock. 15 17 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). 24 - 18 + Optional properties: 19 + - atmel,osc-bypass : boolean property. Set this when a clock signal is directly 20 + provided on XIN. 25 21 26 22 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>; 34 28 }; 35 29 36 30 Power Management Controller (PMC): 37 31 38 32 Required properties: 39 - - compatible : shall be "atmel,<chip>-pmc", "syscon": 33 + - compatible : shall be "atmel,<chip>-pmc", "syscon" or 34 + "microchip,sam9x60-pmc" 40 35 <chip> can be: at91rm9200, at91sam9260, at91sam9261, 41 36 at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15, 42 37 at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5,
+46
Documentation/devicetree/bindings/clock/sifive/fu540-prci.txt
··· 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 + };
+6
Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
··· 11 11 "st,stm32f42xx-rcc" 12 12 "st,stm32f469-rcc" 13 13 "st,stm32f746-rcc" 14 + "st,stm32f769-rcc" 15 + 14 16 - reg: should be register base and length as documented in the 15 17 datasheet 16 18 - #reset-cells: 1, see below ··· 104 102 28 CLK_I2C3 105 103 29 CLK_I2C4 106 104 30 CLK_LPTIMER (LPTimer1 clock) 105 + 31 CLK_PLL_SRC 106 + 32 CLK_DFSDM1 107 + 33 CLK_ADFSDM1 108 + 34 CLK_F769_DSI 107 109 ) 108 110 109 111 Example:
+6
MAINTAINERS
··· 960 960 X: drivers/iio/*/adjd* 961 961 F: drivers/staging/iio/*/ad* 962 962 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 + 963 969 ANDES ARCHITECTURE 964 970 M: Greentime Hu <green.hu@gmail.com> 965 971 M: Vincent Chen <deanbo422@gmail.com>
+3
drivers/clk/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 1 2 2 3 config CLKDEV_LOOKUP 3 4 bool ··· 305 304 Support for Memory Mapped IO Fixed clocks 306 305 307 306 source "drivers/clk/actions/Kconfig" 307 + source "drivers/clk/analogbits/Kconfig" 308 308 source "drivers/clk/bcm/Kconfig" 309 309 source "drivers/clk/hisilicon/Kconfig" 310 310 source "drivers/clk/imgtec/Kconfig" ··· 318 316 source "drivers/clk/qcom/Kconfig" 319 317 source "drivers/clk/renesas/Kconfig" 320 318 source "drivers/clk/samsung/Kconfig" 319 + source "drivers/clk/sifive/Kconfig" 321 320 source "drivers/clk/sprd/Kconfig" 322 321 source "drivers/clk/sunxi/Kconfig" 323 322 source "drivers/clk/sunxi-ng/Kconfig"
+2
drivers/clk/Makefile
··· 66 66 67 67 # please keep this section sorted lexicographically by directory path name 68 68 obj-y += actions/ 69 + obj-y += analogbits/ 69 70 obj-$(CONFIG_COMMON_CLK_AT91) += at91/ 70 71 obj-$(CONFIG_ARCH_ARTPEC) += axis/ 71 72 obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/ ··· 96 95 obj-y += renesas/ 97 96 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 98 97 obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ 98 + obj-$(CONFIG_CLK_SIFIVE) += sifive/ 99 99 obj-$(CONFIG_ARCH_SIRF) += sirf/ 100 100 obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ 101 101 obj-$(CONFIG_PLAT_SPEAR) += spear/
+1 -1
drivers/clk/actions/owl-common.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL common clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-composite.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL composite clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-divider.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL divider clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-factor.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL factor clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-fixed-factor.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL fixed factor clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-gate.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL gate clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-mux.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL mux clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-pll.h
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 2 // 3 3 // OWL pll clock driver 4 4 //
+1 -1
drivers/clk/actions/owl-reset.h
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 2 // 3 3 // Actions Semi Owl SoCs Reset Management Unit driver 4 4 //
+2
drivers/clk/analogbits/Kconfig
··· 1 + config CLK_ANALOGBITS_WRPLL_CLN28HPC 2 + bool
+3
drivers/clk/analogbits/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + obj-$(CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC) += wrpll-cln28hpc.o
+364
drivers/clk/analogbits/wrpll-cln28hpc.c
··· 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 + }
+2
drivers/clk/at91/Makefile
··· 14 14 obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o 15 15 obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o 16 16 obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o 17 + obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o 17 18 obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o 19 + obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o 18 20 obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o 19 21 obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
+7 -7
drivers/clk/at91/at91sam9260.c
··· 41 41 42 42 static u16 sam9260_plla_icpll[] = { 1, 1 }; 43 43 44 - static struct clk_range sam9260_plla_outputs[] = { 44 + static const struct clk_range sam9260_plla_outputs[] = { 45 45 { .min = 80000000, .max = 160000000 }, 46 46 { .min = 150000000, .max = 240000000 }, 47 47 }; ··· 58 58 59 59 static u16 sam9260_pllb_icpll[] = { 1 }; 60 60 61 - static struct clk_range sam9260_pllb_outputs[] = { 61 + static const struct clk_range sam9260_pllb_outputs[] = { 62 62 { .min = 70000000, .max = 130000000 }, 63 63 }; 64 64 ··· 128 128 129 129 static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; 130 130 131 - static struct clk_range sam9g20_plla_outputs[] = { 131 + static const struct clk_range sam9g20_plla_outputs[] = { 132 132 { .min = 745000000, .max = 800000000 }, 133 133 { .min = 695000000, .max = 750000000 }, 134 134 { .min = 645000000, .max = 700000000 }, ··· 151 151 152 152 static u16 sam9g20_pllb_icpll[] = { 0 }; 153 153 154 - static struct clk_range sam9g20_pllb_outputs[] = { 154 + static const struct clk_range sam9g20_pllb_outputs[] = { 155 155 { .min = 30000000, .max = 100000000 }, 156 156 }; 157 157 ··· 182 182 .divisors = { 1, 2, 4, 0 }, 183 183 }; 184 184 185 - static struct clk_range sam9261_plla_outputs[] = { 185 + static const struct clk_range sam9261_plla_outputs[] = { 186 186 { .min = 80000000, .max = 200000000 }, 187 187 { .min = 190000000, .max = 240000000 }, 188 188 }; ··· 199 199 200 200 static u16 sam9261_pllb_icpll[] = { 1 }; 201 201 202 - static struct clk_range sam9261_pllb_outputs[] = { 202 + static const struct clk_range sam9261_pllb_outputs[] = { 203 203 { .min = 70000000, .max = 130000000 }, 204 204 }; 205 205 ··· 262 262 .divisors = { 1, 2, 4, 0 }, 263 263 }; 264 264 265 - static struct clk_range sam9263_pll_outputs[] = { 265 + static const struct clk_range sam9263_pll_outputs[] = { 266 266 { .min = 80000000, .max = 200000000 }, 267 267 { .min = 190000000, .max = 240000000 }, 268 268 };
+1 -1
drivers/clk/at91/at91sam9rl.c
··· 14 14 15 15 static u8 sam9rl_plla_out[] = { 0, 2 }; 16 16 17 - static struct clk_range sam9rl_plla_outputs[] = { 17 + static const struct clk_range sam9rl_plla_outputs[] = { 18 18 { .min = 80000000, .max = 200000000 }, 19 19 { .min = 190000000, .max = 240000000 }, 20 20 };
+10 -1
drivers/clk/at91/at91sam9x5.c
··· 17 17 18 18 static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; 19 19 20 - static struct clk_range plla_outputs[] = { 20 + static const struct clk_range plla_outputs[] = { 21 21 { .min = 745000000, .max = 800000000 }, 22 22 { .min = 695000000, .max = 750000000 }, 23 23 { .min = 645000000, .max = 700000000 }, ··· 47 47 { .n = "udpck", .p = "usbck", .id = 7 }, 48 48 { .n = "pck0", .p = "prog0", .id = 8 }, 49 49 { .n = "pck1", .p = "prog1", .id = 9 }, 50 + }; 51 + 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), 50 57 }; 51 58 52 59 struct pck { ··· 249 242 250 243 for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) { 251 244 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 245 + &at91sam9x5_pcr_layout, 252 246 at91sam9x5_periphck[i].n, 253 247 "masterck", 254 248 at91sam9x5_periphck[i].id, ··· 262 254 263 255 for (i = 0; extra_pcks[i].id; i++) { 264 256 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 257 + &at91sam9x5_pcr_layout, 265 258 extra_pcks[i].n, 266 259 "masterck", 267 260 extra_pcks[i].id,
+25 -23
drivers/clk/at91/clk-generated.c
··· 11 11 * 12 12 */ 13 13 14 + #include <linux/bitfield.h> 14 15 #include <linux/clk-provider.h> 15 16 #include <linux/clkdev.h> 16 17 #include <linux/clk/at91_pmc.h> ··· 32 31 spinlock_t *lock; 33 32 u32 id; 34 33 u32 gckdiv; 34 + const struct clk_pcr_layout *layout; 35 35 u8 parent_id; 36 36 bool audio_pll_allowed; 37 37 }; ··· 49 47 __func__, gck->gckdiv, gck->parent_id); 50 48 51 49 spin_lock_irqsave(gck->lock, flags); 52 - regmap_write(gck->regmap, AT91_PMC_PCR, 53 - (gck->id & AT91_PMC_PCR_PID_MASK)); 54 - regmap_update_bits(gck->regmap, AT91_PMC_PCR, 55 - AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK | 56 - AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, 57 - AT91_PMC_PCR_GCKCSS(gck->parent_id) | 58 - AT91_PMC_PCR_CMD | 59 - AT91_PMC_PCR_GCKDIV(gck->gckdiv) | 50 + regmap_write(gck->regmap, gck->layout->offset, 51 + (gck->id & gck->layout->pid_mask)); 52 + regmap_update_bits(gck->regmap, gck->layout->offset, 53 + AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask | 54 + gck->layout->cmd | AT91_PMC_PCR_GCKEN, 55 + field_prep(gck->layout->gckcss_mask, gck->parent_id) | 56 + gck->layout->cmd | 57 + FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) | 60 58 AT91_PMC_PCR_GCKEN); 61 59 spin_unlock_irqrestore(gck->lock, flags); 62 60 return 0; ··· 68 66 unsigned long flags; 69 67 70 68 spin_lock_irqsave(gck->lock, flags); 71 - regmap_write(gck->regmap, AT91_PMC_PCR, 72 - (gck->id & AT91_PMC_PCR_PID_MASK)); 73 - regmap_update_bits(gck->regmap, AT91_PMC_PCR, 74 - AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, 75 - AT91_PMC_PCR_CMD); 69 + regmap_write(gck->regmap, gck->layout->offset, 70 + (gck->id & gck->layout->pid_mask)); 71 + regmap_update_bits(gck->regmap, gck->layout->offset, 72 + gck->layout->cmd | AT91_PMC_PCR_GCKEN, 73 + gck->layout->cmd); 76 74 spin_unlock_irqrestore(gck->lock, flags); 77 75 } 78 76 ··· 83 81 unsigned int status; 84 82 85 83 spin_lock_irqsave(gck->lock, flags); 86 - regmap_write(gck->regmap, AT91_PMC_PCR, 87 - (gck->id & AT91_PMC_PCR_PID_MASK)); 88 - regmap_read(gck->regmap, AT91_PMC_PCR, &status); 84 + regmap_write(gck->regmap, gck->layout->offset, 85 + (gck->id & gck->layout->pid_mask)); 86 + regmap_read(gck->regmap, gck->layout->offset, &status); 89 87 spin_unlock_irqrestore(gck->lock, flags); 90 88 91 89 return status & AT91_PMC_PCR_GCKEN ? 1 : 0; ··· 261 259 unsigned long flags; 262 260 263 261 spin_lock_irqsave(gck->lock, flags); 264 - regmap_write(gck->regmap, AT91_PMC_PCR, 265 - (gck->id & AT91_PMC_PCR_PID_MASK)); 266 - regmap_read(gck->regmap, AT91_PMC_PCR, &tmp); 262 + regmap_write(gck->regmap, gck->layout->offset, 263 + (gck->id & gck->layout->pid_mask)); 264 + regmap_read(gck->regmap, gck->layout->offset, &tmp); 267 265 spin_unlock_irqrestore(gck->lock, flags); 268 266 269 - gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK) 270 - >> AT91_PMC_PCR_GCKCSS_OFFSET; 271 - gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK) 272 - >> AT91_PMC_PCR_GCKDIV_OFFSET; 267 + gck->parent_id = field_get(gck->layout->gckcss_mask, tmp); 268 + gck->gckdiv = FIELD_GET(AT91_PMC_PCR_GCKDIV_MASK, tmp); 273 269 } 274 270 275 271 struct clk_hw * __init 276 272 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, 273 + const struct clk_pcr_layout *layout, 277 274 const char *name, const char **parent_names, 278 275 u8 num_parents, u8 id, bool pll_audio, 279 276 const struct clk_range *range) ··· 299 298 gck->lock = lock; 300 299 gck->range = *range; 301 300 gck->audio_pll_allowed = pll_audio; 301 + gck->layout = layout; 302 302 303 303 clk_generated_startup(gck); 304 304 hw = &gck->hw;
+5 -3
drivers/clk/at91/clk-master.c
··· 29 29 struct regmap *regmap; 30 30 const struct clk_master_layout *layout; 31 31 const struct clk_master_characteristics *characteristics; 32 + u32 mckr; 32 33 }; 33 34 34 35 static inline bool clk_master_ready(struct regmap *regmap) ··· 70 69 master->characteristics; 71 70 unsigned int mckr; 72 71 73 - regmap_read(master->regmap, AT91_PMC_MCKR, &mckr); 72 + regmap_read(master->regmap, master->layout->offset, &mckr); 74 73 mckr &= layout->mask; 75 74 76 75 pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK; ··· 96 95 struct clk_master *master = to_clk_master(hw); 97 96 unsigned int mckr; 98 97 99 - regmap_read(master->regmap, AT91_PMC_MCKR, &mckr); 98 + regmap_read(master->regmap, master->layout->offset, &mckr); 100 99 101 100 return mckr & AT91_PMC_CSS; 102 101 } ··· 148 147 return hw; 149 148 } 150 149 151 - 152 150 const struct clk_master_layout at91rm9200_master_layout = { 153 151 .mask = 0x31F, 154 152 .pres_shift = 2, 153 + .offset = AT91_PMC_MCKR, 155 154 }; 156 155 157 156 const struct clk_master_layout at91sam9x5_master_layout = { 158 157 .mask = 0x373, 159 158 .pres_shift = 4, 159 + .offset = AT91_PMC_MCKR, 160 160 };
+24 -22
drivers/clk/at91/clk-peripheral.c
··· 8 8 * 9 9 */ 10 10 11 + #include <linux/bitops.h> 11 12 #include <linux/clk-provider.h> 12 13 #include <linux/clkdev.h> 13 14 #include <linux/clk/at91_pmc.h> ··· 23 22 #define PERIPHERAL_ID_MIN 2 24 23 #define PERIPHERAL_ID_MAX 31 25 24 #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX)) 26 - 27 - #define PERIPHERAL_RSHIFT_MASK 0x3 28 - #define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK) 29 25 30 26 #define PERIPHERAL_MAX_SHIFT 3 31 27 ··· 41 43 spinlock_t *lock; 42 44 u32 id; 43 45 u32 div; 46 + const struct clk_pcr_layout *layout; 44 47 bool auto_div; 45 48 }; 46 49 ··· 168 169 return 0; 169 170 170 171 spin_lock_irqsave(periph->lock, flags); 171 - regmap_write(periph->regmap, AT91_PMC_PCR, 172 - (periph->id & AT91_PMC_PCR_PID_MASK)); 173 - regmap_update_bits(periph->regmap, AT91_PMC_PCR, 174 - AT91_PMC_PCR_DIV_MASK | AT91_PMC_PCR_CMD | 172 + regmap_write(periph->regmap, periph->layout->offset, 173 + (periph->id & periph->layout->pid_mask)); 174 + regmap_update_bits(periph->regmap, periph->layout->offset, 175 + periph->layout->div_mask | periph->layout->cmd | 175 176 AT91_PMC_PCR_EN, 176 - AT91_PMC_PCR_DIV(periph->div) | 177 - AT91_PMC_PCR_CMD | 177 + field_prep(periph->layout->div_mask, periph->div) | 178 + periph->layout->cmd | 178 179 AT91_PMC_PCR_EN); 179 180 spin_unlock_irqrestore(periph->lock, flags); 180 181 ··· 190 191 return; 191 192 192 193 spin_lock_irqsave(periph->lock, flags); 193 - regmap_write(periph->regmap, AT91_PMC_PCR, 194 - (periph->id & AT91_PMC_PCR_PID_MASK)); 195 - regmap_update_bits(periph->regmap, AT91_PMC_PCR, 196 - AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD, 197 - AT91_PMC_PCR_CMD); 194 + regmap_write(periph->regmap, periph->layout->offset, 195 + (periph->id & periph->layout->pid_mask)); 196 + regmap_update_bits(periph->regmap, periph->layout->offset, 197 + AT91_PMC_PCR_EN | periph->layout->cmd, 198 + periph->layout->cmd); 198 199 spin_unlock_irqrestore(periph->lock, flags); 199 200 } 200 201 ··· 208 209 return 1; 209 210 210 211 spin_lock_irqsave(periph->lock, flags); 211 - regmap_write(periph->regmap, AT91_PMC_PCR, 212 - (periph->id & AT91_PMC_PCR_PID_MASK)); 213 - regmap_read(periph->regmap, AT91_PMC_PCR, &status); 212 + regmap_write(periph->regmap, periph->layout->offset, 213 + (periph->id & periph->layout->pid_mask)); 214 + regmap_read(periph->regmap, periph->layout->offset, &status); 214 215 spin_unlock_irqrestore(periph->lock, flags); 215 216 216 217 return status & AT91_PMC_PCR_EN ? 1 : 0; ··· 228 229 return parent_rate; 229 230 230 231 spin_lock_irqsave(periph->lock, flags); 231 - regmap_write(periph->regmap, AT91_PMC_PCR, 232 - (periph->id & AT91_PMC_PCR_PID_MASK)); 233 - regmap_read(periph->regmap, AT91_PMC_PCR, &status); 232 + regmap_write(periph->regmap, periph->layout->offset, 233 + (periph->id & periph->layout->pid_mask)); 234 + regmap_read(periph->regmap, periph->layout->offset, &status); 234 235 spin_unlock_irqrestore(periph->lock, flags); 235 236 236 237 if (status & AT91_PMC_PCR_EN) { 237 - periph->div = PERIPHERAL_RSHIFT(status); 238 + periph->div = field_get(periph->layout->div_mask, status); 238 239 periph->auto_div = false; 239 240 } else { 240 241 clk_sam9x5_peripheral_autodiv(periph); ··· 327 328 328 329 struct clk_hw * __init 329 330 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, 331 + const struct clk_pcr_layout *layout, 330 332 const char *name, const char *parent_name, 331 333 u32 id, const struct clk_range *range) 332 334 { ··· 354 354 periph->div = 0; 355 355 periph->regmap = regmap; 356 356 periph->lock = lock; 357 - periph->auto_div = true; 357 + if (layout->div_mask) 358 + periph->auto_div = true; 359 + periph->layout = layout; 358 360 periph->range = *range; 359 361 360 362 hw = &periph->hw;
+330
drivers/clk/at91/clk-sam9x60-pll.c
··· 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 +
+27 -6
drivers/clk/at91/clk-usb.c
··· 23 23 #define RM9200_USB_DIV_SHIFT 28 24 24 #define RM9200_USB_DIV_TAB_SIZE 4 25 25 26 + #define SAM9X5_USBS_MASK GENMASK(0, 0) 27 + #define SAM9X60_USBS_MASK GENMASK(1, 0) 28 + 26 29 struct at91sam9x5_clk_usb { 27 30 struct clk_hw hw; 28 31 struct regmap *regmap; 32 + u32 usbs_mask; 29 33 }; 30 34 31 35 #define to_at91sam9x5_clk_usb(hw) \ ··· 115 111 if (index > 1) 116 112 return -EINVAL; 117 113 118 - regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 119 - index ? AT91_PMC_USBS : 0); 114 + regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index); 120 115 121 116 return 0; 122 117 } ··· 127 124 128 125 regmap_read(usb->regmap, AT91_PMC_USB, &usbr); 129 126 130 - return usbr & AT91_PMC_USBS; 127 + return usbr & usb->usbs_mask; 131 128 } 132 129 133 130 static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, ··· 193 190 .set_rate = at91sam9x5_clk_usb_set_rate, 194 191 }; 195 192 196 - struct clk_hw * __init 197 - at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, 198 - const char **parent_names, u8 num_parents) 193 + static struct clk_hw * __init 194 + _at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, 195 + const char **parent_names, u8 num_parents, 196 + u32 usbs_mask) 199 197 { 200 198 struct at91sam9x5_clk_usb *usb; 201 199 struct clk_hw *hw; ··· 216 212 217 213 usb->hw.init = &init; 218 214 usb->regmap = regmap; 215 + usb->usbs_mask = SAM9X5_USBS_MASK; 219 216 220 217 hw = &usb->hw; 221 218 ret = clk_hw_register(NULL, &usb->hw); ··· 226 221 } 227 222 228 223 return hw; 224 + } 225 + 226 + struct clk_hw * __init 227 + at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, 228 + const char **parent_names, u8 num_parents) 229 + { 230 + return _at91sam9x5_clk_register_usb(regmap, name, parent_names, 231 + num_parents, SAM9X5_USBS_MASK); 232 + } 233 + 234 + struct clk_hw * __init 235 + sam9x60_clk_register_usb(struct regmap *regmap, const char *name, 236 + const char **parent_names, u8 num_parents) 237 + { 238 + return _at91sam9x5_clk_register_usb(regmap, name, parent_names, 239 + num_parents, SAM9X60_USBS_MASK); 229 240 } 230 241 231 242 struct clk_hw * __init
+11 -1
drivers/clk/at91/dt-compat.c
··· 93 93 of_sama5d2_clk_audio_pll_pmc_setup); 94 94 #endif /* CONFIG_HAVE_AT91_AUDIO_PLL */ 95 95 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 + 96 104 #ifdef CONFIG_HAVE_AT91_GENERATED_CLK 97 105 #define GENERATED_SOURCE_MAX 6 98 106 ··· 154 146 id == GCK_ID_CLASSD)) 155 147 pll_audio = true; 156 148 157 - hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, 149 + hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, 150 + &dt_pcr_layout, name, 158 151 parent_names, num_parents, 159 152 id, pll_audio, &range); 160 153 if (IS_ERR(hw)) ··· 457 448 458 449 hw = at91_clk_register_sam9x5_peripheral(regmap, 459 450 &pmc_pcr_lock, 451 + &dt_pcr_layout, 460 452 name, 461 453 parent_name, 462 454 id, &range);
+24 -1
drivers/clk/at91/pmc.h
··· 38 38 #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} 39 39 40 40 struct clk_master_layout { 41 + u32 offset; 41 42 u32 mask; 42 43 u8 pres_shift; 43 44 }; ··· 66 65 struct clk_pll_characteristics { 67 66 struct clk_range input; 68 67 int num_output; 69 - struct clk_range *output; 68 + const struct clk_range *output; 70 69 u16 *icpll; 71 70 u8 *out; 71 + u8 upll : 1; 72 72 }; 73 73 74 74 struct clk_programmable_layout { ··· 83 81 extern const struct clk_programmable_layout at91rm9200_programmable_layout; 84 82 extern const struct clk_programmable_layout at91sam9g45_programmable_layout; 85 83 extern const struct clk_programmable_layout at91sam9x5_programmable_layout; 84 + 85 + struct clk_pcr_layout { 86 + u32 offset; 87 + u32 cmd; 88 + u32 div_mask; 89 + u32 gckcss_mask; 90 + u32 pid_mask; 91 + }; 92 + 93 + #define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1)) 94 + #define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask)) 86 95 87 96 #define ndck(a, s) (a[s - 1].id + 1) 88 97 #define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1) ··· 120 107 121 108 struct clk_hw * __init 122 109 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, 110 + const struct clk_pcr_layout *layout, 123 111 const char *name, const char **parent_names, 124 112 u8 num_parents, u8 id, bool pll_audio, 125 113 const struct clk_range *range); ··· 159 145 const char *parent_name, u32 id); 160 146 struct clk_hw * __init 161 147 at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, 148 + const struct clk_pcr_layout *layout, 162 149 const char *name, const char *parent_name, 163 150 u32 id, const struct clk_range *range); 164 151 ··· 171 156 struct clk_hw * __init 172 157 at91_clk_register_plldiv(struct regmap *regmap, const char *name, 173 158 const char *parent_name); 159 + 160 + struct clk_hw * __init 161 + sam9x60_clk_register_pll(struct regmap *regmap, spinlock_t *lock, 162 + const char *name, const char *parent_name, u8 id, 163 + const struct clk_pll_characteristics *characteristics); 174 164 175 165 struct clk_hw * __init 176 166 at91_clk_register_programmable(struct regmap *regmap, const char *name, ··· 202 182 struct clk_hw * __init 203 183 at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name, 204 184 const char *parent_name); 185 + struct clk_hw * __init 186 + sam9x60_clk_register_usb(struct regmap *regmap, const char *name, 187 + const char **parent_names, u8 num_parents); 205 188 struct clk_hw * __init 206 189 at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, 207 190 const char *parent_name, const u32 *divisors);
+307
drivers/clk/at91/sam9x60.c
··· 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);
+11 -1
drivers/clk/at91/sama5d2.c
··· 16 16 17 17 static u16 plla_icpll[] = { 0 }; 18 18 19 - static struct clk_range plla_outputs[] = { 19 + static const struct clk_range plla_outputs[] = { 20 20 { .min = 600000000, .max = 1200000000 }, 21 21 }; 22 22 ··· 26 26 .output = plla_outputs, 27 27 .icpll = plla_icpll, 28 28 .out = plla_out, 29 + }; 30 + 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), 29 36 }; 30 37 31 38 static const struct { ··· 281 274 282 275 for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) { 283 276 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 277 + &sama5d2_pcr_layout, 284 278 sama5d2_periphck[i].n, 285 279 "masterck", 286 280 sama5d2_periphck[i].id, ··· 294 286 295 287 for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) { 296 288 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 289 + &sama5d2_pcr_layout, 297 290 sama5d2_periph32ck[i].n, 298 291 "h32mxck", 299 292 sama5d2_periph32ck[i].id, ··· 313 304 parent_names[5] = "audiopll_pmcck"; 314 305 for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) { 315 306 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, 307 + &sama5d2_pcr_layout, 316 308 sama5d2_gck[i].n, 317 309 parent_names, 6, 318 310 sama5d2_gck[i].id,
+9 -1
drivers/clk/at91/sama5d4.c
··· 16 16 17 17 static u16 plla_icpll[] = { 0 }; 18 18 19 - static struct clk_range plla_outputs[] = { 19 + static const struct clk_range plla_outputs[] = { 20 20 { .min = 600000000, .max = 1200000000 }, 21 21 }; 22 22 ··· 26 26 .output = plla_outputs, 27 27 .icpll = plla_icpll, 28 28 .out = plla_out, 29 + }; 30 + 31 + static const struct clk_pcr_layout sama5d4_pcr_layout = { 32 + .offset = 0x10c, 33 + .cmd = BIT(12), 34 + .pid_mask = GENMASK(6, 0), 29 35 }; 30 36 31 37 static const struct { ··· 238 232 239 233 for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) { 240 234 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 235 + &sama5d4_pcr_layout, 241 236 sama5d4_periphck[i].n, 242 237 "masterck", 243 238 sama5d4_periphck[i].id, ··· 251 244 252 245 for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) { 253 246 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, 247 + &sama5d4_pcr_layout, 254 248 sama5d4_periph32ck[i].n, 255 249 "h32mxck", 256 250 sama5d4_periph32ck[i].id,
+55 -95
drivers/clk/at91/sckc.c
··· 152 152 return hw; 153 153 } 154 154 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 - 177 155 static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, 178 156 unsigned long parent_rate) 179 157 { ··· 244 266 return hw; 245 267 } 246 268 247 - static void __init 248 - of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, void __iomem *sckcr) 249 - { 250 - struct clk_hw *hw; 251 - u32 frequency = 0; 252 - u32 accuracy = 0; 253 - u32 startup = 0; 254 - const char *name = np->name; 255 - 256 - of_property_read_string(np, "clock-output-names", &name); 257 - of_property_read_u32(np, "clock-frequency", &frequency); 258 - of_property_read_u32(np, "clock-accuracy", &accuracy); 259 - of_property_read_u32(np, "atmel,startup-time-usec", &startup); 260 - 261 - hw = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy, 262 - startup); 263 - if (IS_ERR(hw)) 264 - return; 265 - 266 - of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); 267 - } 268 - 269 269 static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) 270 270 { 271 271 struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); ··· 321 365 return hw; 322 366 } 323 367 324 - static void __init 325 - of_at91sam9x5_clk_slow_setup(struct device_node *np, void __iomem *sckcr) 368 + static void __init at91sam9x5_sckc_register(struct device_node *np, 369 + unsigned int rc_osc_startup_us) 326 370 { 327 - struct clk_hw *hw; 328 - const char *parent_names[2]; 329 - unsigned int num_parents; 330 - const char *name = np->name; 331 - 332 - num_parents = of_clk_get_parent_count(np); 333 - if (num_parents == 0 || num_parents > 2) 334 - return; 335 - 336 - of_clk_parent_fill(np, parent_names, num_parents); 337 - 338 - of_property_read_string(np, "clock-output-names", &name); 339 - 340 - hw = at91_clk_register_sam9x5_slow(sckcr, name, parent_names, 341 - num_parents); 342 - if (IS_ERR(hw)) 343 - return; 344 - 345 - of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); 346 - } 347 - 348 - static const struct of_device_id sckc_clk_ids[] __initconst = { 349 - /* Slow clock */ 350 - { 351 - .compatible = "atmel,at91sam9x5-clk-slow-osc", 352 - .data = of_at91sam9x5_clk_slow_osc_setup, 353 - }, 354 - { 355 - .compatible = "atmel,at91sam9x5-clk-slow-rc-osc", 356 - .data = of_at91sam9x5_clk_slow_rc_osc_setup, 357 - }, 358 - { 359 - .compatible = "atmel,at91sam9x5-clk-slow", 360 - .data = of_at91sam9x5_clk_slow_setup, 361 - }, 362 - { /*sentinel*/ } 363 - }; 364 - 365 - static void __init of_at91sam9x5_sckc_setup(struct device_node *np) 366 - { 367 - struct device_node *childnp; 368 - void (*clk_setup)(struct device_node *, void __iomem *); 369 - const struct of_device_id *clk_id; 371 + const char *parent_names[2] = { "slow_rc_osc", "slow_osc" }; 370 372 void __iomem *regbase = of_iomap(np, 0); 373 + struct device_node *child = NULL; 374 + const char *xtal_name; 375 + struct clk_hw *hw; 376 + bool bypass; 371 377 372 378 if (!regbase) 373 379 return; 374 380 375 - for_each_child_of_node(np, childnp) { 376 - clk_id = of_match_node(sckc_clk_ids, childnp); 377 - if (!clk_id) 378 - continue; 379 - clk_setup = clk_id->data; 380 - clk_setup(childnp, regbase); 381 + hw = at91_clk_register_slow_rc_osc(regbase, parent_names[0], 32768, 382 + 50000000, rc_osc_startup_us); 383 + if (IS_ERR(hw)) 384 + return; 385 + 386 + xtal_name = of_clk_get_parent_name(np, 0); 387 + if (!xtal_name) { 388 + /* DT backward compatibility */ 389 + child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc"); 390 + if (!child) 391 + return; 392 + 393 + xtal_name = of_clk_get_parent_name(child, 0); 394 + bypass = of_property_read_bool(child, "atmel,osc-bypass"); 395 + 396 + child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow"); 397 + } else { 398 + bypass = of_property_read_bool(np, "atmel,osc-bypass"); 381 399 } 400 + 401 + if (!xtal_name) 402 + return; 403 + 404 + hw = at91_clk_register_slow_osc(regbase, parent_names[1], xtal_name, 405 + 1200000, bypass); 406 + if (IS_ERR(hw)) 407 + return; 408 + 409 + hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2); 410 + if (IS_ERR(hw)) 411 + return; 412 + 413 + of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); 414 + 415 + /* DT backward compatibility */ 416 + if (child) 417 + of_clk_add_hw_provider(child, of_clk_hw_simple_get, hw); 418 + } 419 + 420 + static void __init of_at91sam9x5_sckc_setup(struct device_node *np) 421 + { 422 + at91sam9x5_sckc_register(np, 75); 382 423 } 383 424 CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc", 384 425 of_at91sam9x5_sckc_setup); 426 + 427 + static void __init of_sama5d3_sckc_setup(struct device_node *np) 428 + { 429 + at91sam9x5_sckc_register(np, 500); 430 + } 431 + CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc", 432 + of_sama5d3_sckc_setup); 385 433 386 434 static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw) 387 435 {
+299 -8
drivers/clk/clk-stm32f4.c
··· 300 300 { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, 301 301 }; 302 302 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 + 303 382 /* 304 383 * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx 305 384 * have gate bits associated with them. Its combined hweight is 71. ··· 396 317 static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull, 397 318 0x0000000000000003ull, 398 319 0x04f77f833e01c9ffull }; 320 + 321 + static const u64 stm32f769_gate_map[MAX_GATE_MAP] = { 0x000000f37ef417ffull, 322 + 0x0000000000000003ull, 323 + 0x44F77F833E01EDFFull }; 399 324 400 325 static const u64 *stm32f4_gate_map; 401 326 ··· 1131 1048 "no-clock", "lse", "lsi", "hse-rtc" 1132 1049 }; 1133 1050 1051 + static const char *pll_src = "pll-src"; 1052 + 1053 + static const char *pllsrc_parent[2] = { "hsi", NULL }; 1054 + 1134 1055 static const char *dsi_parent[2] = { NULL, "pll-r" }; 1135 1056 1136 1057 static const char *lcd_parent[1] = { "pllsai-r-div" }; ··· 1158 1071 static const char *uart_parents2[4] = { "apb1_div", "sys", "hsi", "lse" }; 1159 1072 1160 1073 static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" }; 1074 + 1075 + static const char * const dfsdm1_src[] = { "apb2_div", "sys" }; 1076 + static const char * const adsfdm1_parent[] = { "sai1_clk", "sai2_clk" }; 1161 1077 1162 1078 struct stm32_aux_clk { 1163 1079 int idx; ··· 1403 1313 }, 1404 1314 }; 1405 1315 1316 + static const struct stm32_aux_clk stm32f769_aux_clk[] = { 1317 + { 1318 + CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent), 1319 + NO_MUX, 0, 0, 1320 + STM32F4_RCC_APB2ENR, 26, 1321 + CLK_SET_RATE_PARENT 1322 + }, 1323 + { 1324 + CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents), 1325 + STM32F4_RCC_CFGR, 23, 1, 1326 + NO_GATE, 0, 1327 + CLK_SET_RATE_PARENT 1328 + }, 1329 + { 1330 + CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents), 1331 + STM32F4_RCC_DCKCFGR, 20, 3, 1332 + STM32F4_RCC_APB2ENR, 22, 1333 + CLK_SET_RATE_PARENT 1334 + }, 1335 + { 1336 + CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents), 1337 + STM32F4_RCC_DCKCFGR, 22, 3, 1338 + STM32F4_RCC_APB2ENR, 23, 1339 + CLK_SET_RATE_PARENT 1340 + }, 1341 + { 1342 + NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents), 1343 + STM32F7_RCC_DCKCFGR2, 27, 1, 1344 + NO_GATE, 0, 1345 + 0 1346 + }, 1347 + { 1348 + NO_IDX, "sdmux1", sdmux_parents, ARRAY_SIZE(sdmux_parents), 1349 + STM32F7_RCC_DCKCFGR2, 28, 1, 1350 + NO_GATE, 0, 1351 + 0 1352 + }, 1353 + { 1354 + NO_IDX, "sdmux2", sdmux_parents, ARRAY_SIZE(sdmux_parents), 1355 + STM32F7_RCC_DCKCFGR2, 29, 1, 1356 + NO_GATE, 0, 1357 + 0 1358 + }, 1359 + { 1360 + CLK_HDMI_CEC, "hdmi-cec", 1361 + hdmi_parents, ARRAY_SIZE(hdmi_parents), 1362 + STM32F7_RCC_DCKCFGR2, 26, 1, 1363 + NO_GATE, 0, 1364 + 0 1365 + }, 1366 + { 1367 + CLK_SPDIF, "spdif-rx", 1368 + spdif_parent, ARRAY_SIZE(spdif_parent), 1369 + STM32F7_RCC_DCKCFGR2, 22, 3, 1370 + STM32F4_RCC_APB2ENR, 23, 1371 + CLK_SET_RATE_PARENT 1372 + }, 1373 + { 1374 + CLK_USART1, "usart1", 1375 + uart_parents1, ARRAY_SIZE(uart_parents1), 1376 + STM32F7_RCC_DCKCFGR2, 0, 3, 1377 + STM32F4_RCC_APB2ENR, 4, 1378 + CLK_SET_RATE_PARENT, 1379 + }, 1380 + { 1381 + CLK_USART2, "usart2", 1382 + uart_parents2, ARRAY_SIZE(uart_parents1), 1383 + STM32F7_RCC_DCKCFGR2, 2, 3, 1384 + STM32F4_RCC_APB1ENR, 17, 1385 + CLK_SET_RATE_PARENT, 1386 + }, 1387 + { 1388 + CLK_USART3, "usart3", 1389 + uart_parents2, ARRAY_SIZE(uart_parents1), 1390 + STM32F7_RCC_DCKCFGR2, 4, 3, 1391 + STM32F4_RCC_APB1ENR, 18, 1392 + CLK_SET_RATE_PARENT, 1393 + }, 1394 + { 1395 + CLK_UART4, "uart4", 1396 + uart_parents2, ARRAY_SIZE(uart_parents1), 1397 + STM32F7_RCC_DCKCFGR2, 6, 3, 1398 + STM32F4_RCC_APB1ENR, 19, 1399 + CLK_SET_RATE_PARENT, 1400 + }, 1401 + { 1402 + CLK_UART5, "uart5", 1403 + uart_parents2, ARRAY_SIZE(uart_parents1), 1404 + STM32F7_RCC_DCKCFGR2, 8, 3, 1405 + STM32F4_RCC_APB1ENR, 20, 1406 + CLK_SET_RATE_PARENT, 1407 + }, 1408 + { 1409 + CLK_USART6, "usart6", 1410 + uart_parents1, ARRAY_SIZE(uart_parents1), 1411 + STM32F7_RCC_DCKCFGR2, 10, 3, 1412 + STM32F4_RCC_APB2ENR, 5, 1413 + CLK_SET_RATE_PARENT, 1414 + }, 1415 + { 1416 + CLK_UART7, "uart7", 1417 + uart_parents2, ARRAY_SIZE(uart_parents1), 1418 + STM32F7_RCC_DCKCFGR2, 12, 3, 1419 + STM32F4_RCC_APB1ENR, 30, 1420 + CLK_SET_RATE_PARENT, 1421 + }, 1422 + { 1423 + CLK_UART8, "uart8", 1424 + uart_parents2, ARRAY_SIZE(uart_parents1), 1425 + STM32F7_RCC_DCKCFGR2, 14, 3, 1426 + STM32F4_RCC_APB1ENR, 31, 1427 + CLK_SET_RATE_PARENT, 1428 + }, 1429 + { 1430 + CLK_I2C1, "i2c1", 1431 + i2c_parents, ARRAY_SIZE(i2c_parents), 1432 + STM32F7_RCC_DCKCFGR2, 16, 3, 1433 + STM32F4_RCC_APB1ENR, 21, 1434 + CLK_SET_RATE_PARENT, 1435 + }, 1436 + { 1437 + CLK_I2C2, "i2c2", 1438 + i2c_parents, ARRAY_SIZE(i2c_parents), 1439 + STM32F7_RCC_DCKCFGR2, 18, 3, 1440 + STM32F4_RCC_APB1ENR, 22, 1441 + CLK_SET_RATE_PARENT, 1442 + }, 1443 + { 1444 + CLK_I2C3, "i2c3", 1445 + i2c_parents, ARRAY_SIZE(i2c_parents), 1446 + STM32F7_RCC_DCKCFGR2, 20, 3, 1447 + STM32F4_RCC_APB1ENR, 23, 1448 + CLK_SET_RATE_PARENT, 1449 + }, 1450 + { 1451 + CLK_I2C4, "i2c4", 1452 + i2c_parents, ARRAY_SIZE(i2c_parents), 1453 + STM32F7_RCC_DCKCFGR2, 22, 3, 1454 + STM32F4_RCC_APB1ENR, 24, 1455 + CLK_SET_RATE_PARENT, 1456 + }, 1457 + { 1458 + CLK_LPTIMER, "lptim1", 1459 + lptim_parent, ARRAY_SIZE(lptim_parent), 1460 + STM32F7_RCC_DCKCFGR2, 24, 3, 1461 + STM32F4_RCC_APB1ENR, 9, 1462 + CLK_SET_RATE_PARENT 1463 + }, 1464 + { 1465 + CLK_F769_DSI, "dsi", 1466 + dsi_parent, ARRAY_SIZE(dsi_parent), 1467 + STM32F7_RCC_DCKCFGR2, 0, 1, 1468 + STM32F4_RCC_APB2ENR, 27, 1469 + CLK_SET_RATE_PARENT 1470 + }, 1471 + { 1472 + CLK_DFSDM1, "dfsdm1", 1473 + dfsdm1_src, ARRAY_SIZE(dfsdm1_src), 1474 + STM32F4_RCC_DCKCFGR, 25, 1, 1475 + STM32F4_RCC_APB2ENR, 29, 1476 + CLK_SET_RATE_PARENT 1477 + }, 1478 + { 1479 + CLK_ADFSDM1, "adfsdm1", 1480 + adsfdm1_parent, ARRAY_SIZE(adsfdm1_parent), 1481 + STM32F4_RCC_DCKCFGR, 26, 1, 1482 + STM32F4_RCC_APB2ENR, 29, 1483 + CLK_SET_RATE_PARENT 1484 + }, 1485 + }; 1486 + 1406 1487 static const struct stm32f4_clk_data stm32f429_clk_data = { 1407 1488 .end_primary = END_PRIMARY_CLK, 1408 1489 .gates_data = stm32f429_gates, ··· 1604 1343 .aux_clk_num = ARRAY_SIZE(stm32f746_aux_clk), 1605 1344 }; 1606 1345 1346 + static const struct stm32f4_clk_data stm32f769_clk_data = { 1347 + .end_primary = END_PRIMARY_CLK_F7, 1348 + .gates_data = stm32f769_gates, 1349 + .gates_map = stm32f769_gate_map, 1350 + .gates_num = ARRAY_SIZE(stm32f769_gates), 1351 + .pll_data = stm32f469_pll, 1352 + .aux_clk = stm32f769_aux_clk, 1353 + .aux_clk_num = ARRAY_SIZE(stm32f769_aux_clk), 1354 + }; 1355 + 1607 1356 static const struct of_device_id stm32f4_of_match[] = { 1608 1357 { 1609 1358 .compatible = "st,stm32f42xx-rcc", ··· 1626 1355 { 1627 1356 .compatible = "st,stm32f746-rcc", 1628 1357 .data = &stm32f746_clk_data 1358 + }, 1359 + { 1360 + .compatible = "st,stm32f769-rcc", 1361 + .data = &stm32f769_clk_data 1629 1362 }, 1630 1363 {} 1631 1364 }; ··· 1702 1427 int n; 1703 1428 const struct of_device_id *match; 1704 1429 const struct stm32f4_clk_data *data; 1705 - unsigned long pllcfgr; 1706 - const char *pllsrc; 1707 1430 unsigned long pllm; 1431 + struct clk_hw *pll_src_hw; 1708 1432 1709 1433 base = of_iomap(np, 0); 1710 1434 if (!base) { ··· 1734 1460 1735 1461 hse_clk = of_clk_get_parent_name(np, 0); 1736 1462 dsi_parent[0] = hse_clk; 1463 + pllsrc_parent[1] = hse_clk; 1737 1464 1738 1465 i2s_in_clk = of_clk_get_parent_name(np, 1); 1739 1466 1740 1467 i2s_parents[1] = i2s_in_clk; 1741 1468 sai_parents[2] = i2s_in_clk; 1742 1469 1470 + if (of_device_is_compatible(np, "st,stm32f769-rcc")) { 1471 + clk_hw_register_gate(NULL, "dfsdm1_apb", "apb2_div", 0, 1472 + base + STM32F4_RCC_APB2ENR, 29, 1473 + CLK_IGNORE_UNUSED, &stm32f4_clk_lock); 1474 + dsi_parent[0] = pll_src; 1475 + sai_parents[3] = pll_src; 1476 + } 1477 + 1743 1478 clks[CLK_HSI] = clk_hw_register_fixed_rate_with_accuracy(NULL, "hsi", 1744 1479 NULL, 0, 16000000, 160000); 1745 1480 1746 - pllcfgr = readl(base + STM32F4_RCC_PLLCFGR); 1747 - pllsrc = pllcfgr & BIT(22) ? hse_clk : "hsi"; 1748 - pllm = pllcfgr & 0x3f; 1481 + pll_src_hw = clk_hw_register_mux(NULL, pll_src, pllsrc_parent, 1482 + ARRAY_SIZE(pllsrc_parent), 0, 1483 + base + STM32F4_RCC_PLLCFGR, 22, 1, 0, 1484 + &stm32f4_clk_lock); 1749 1485 1750 - clk_hw_register_fixed_factor(NULL, "vco_in", pllsrc, 1751 - 0, 1, pllm); 1486 + pllm = readl(base + STM32F4_RCC_PLLCFGR) & 0x3f; 1487 + 1488 + clk_hw_register_fixed_factor(NULL, "vco_in", pll_src, 1489 + 0, 1, pllm); 1752 1490 1753 1491 stm32f4_rcc_register_pll("vco_in", &data->pll_data[0], 1754 1492 &stm32f4_clk_lock); ··· 1898 1612 clks[aux_clk->idx] = hw; 1899 1613 } 1900 1614 1901 - if (of_device_is_compatible(np, "st,stm32f746-rcc")) 1615 + if (of_device_is_compatible(np, "st,stm32f746-rcc")) { 1902 1616 1903 1617 clk_hw_register_fixed_factor(NULL, "hsi_div488", "hsi", 0, 1904 1618 1, 488); 1905 1619 1620 + clks[CLK_PLL_SRC] = pll_src_hw; 1621 + } 1622 + 1906 1623 of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL); 1624 + 1907 1625 return; 1908 1626 fail: 1909 1627 kfree(clks); ··· 1916 1626 CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init); 1917 1627 CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init); 1918 1628 CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init); 1629 + CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);
+3
drivers/clk/clk-stm32mp1.c
··· 1402 1402 G_CRYP1, 1403 1403 G_HASH1, 1404 1404 G_BKPSRAM, 1405 + G_DDRPERFM, 1405 1406 1406 1407 G_LAST 1407 1408 }; ··· 1489 1488 K_GATE(G_STGENRO, RCC_APB4ENSETR, 20, 0), 1490 1489 K_MGATE(G_USBPHY, RCC_APB4ENSETR, 16, 0), 1491 1490 K_GATE(G_IWDG2, RCC_APB4ENSETR, 15, 0), 1491 + K_GATE(G_DDRPERFM, RCC_APB4ENSETR, 8, 0), 1492 1492 K_MGATE(G_DSI, RCC_APB4ENSETR, 4, 0), 1493 1493 K_MGATE(G_LTDC, RCC_APB4ENSETR, 0, 0), 1494 1494 ··· 1901 1899 PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1), 1902 1900 PCLK(USBH, "usbh", "ck_axi", 0, G_USBH), 1903 1901 PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP), 1902 + PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, G_DDRPERFM), 1904 1903 1905 1904 /* Kernel clocks */ 1906 1905 KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
+1 -1
drivers/clk/davinci/pll.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* 3 3 * Clock driver for TI Davinci PSC controllers 4 4 *
+1 -1
drivers/clk/davinci/psc.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* 3 3 * Clock driver for TI Davinci PSC controllers 4 4 *
+1 -1
drivers/clk/qcom/clk-regmap-mux-div.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* 3 3 * Copyright (c) 2017, Linaro Limited 4 4 * Author: Georgi Djakov <georgi.djakov@linaro.org>
+2 -2
drivers/clk/renesas/rcar-gen2-cpg.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 2 - * 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 3 * R-Car Gen2 Clock Pulse Generator 4 4 * 5 5 * Copyright (C) 2016 Cogent Embedded Inc.
+2 -2
drivers/clk/renesas/rcar-gen3-cpg.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 2 - * 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 3 * R-Car Gen3 Clock Pulse Generator 4 4 * 5 5 * Copyright (C) 2015-2018 Glider bvba
+2 -2
drivers/clk/renesas/renesas-cpg-mssr.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 2 - * 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 3 * Renesas Clock Pulse Generator / Module Standby and Software Reset 4 4 * 5 5 * Copyright (C) 2015 Glider bvba
+18
drivers/clk/sifive/Kconfig
··· 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
+1
drivers/clk/sifive/Makefile
··· 1 + obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI) += fu540-prci.o
+626
drivers/clk/sifive/fu540-prci.c
··· 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);
+1 -1
drivers/clk/sprd/common.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 // 3 3 // Spreadtrum clock infrastructure 4 4 //
+1 -1
drivers/clk/sprd/composite.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 // 3 3 // Spreadtrum composite clock driver 4 4 //
+1 -1
drivers/clk/sprd/div.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 // 3 3 // Spreadtrum divider clock driver 4 4 //
+1 -1
drivers/clk/sprd/gate.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 // 3 3 // Spreadtrum gate clock driver 4 4 //
+1 -1
drivers/clk/sprd/mux.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 // 3 3 // Spreadtrum multiplexer clock driver 4 4 //
+1 -1
drivers/clk/sprd/pll.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 // 3 3 // Spreadtrum pll clock driver 4 4 //
+1 -1
drivers/clk/sunxi-ng/ccu-sun50i-h6.h
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 2 /* 3 3 * Copyright 2016 Icenowy Zheng <icenowy@aosc.io> 4 4 */
+2 -2
drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ 2 - * 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 3 * Copyright 2017 Icenowy Zheng <icenowy@aosc.io> 4 4 * 5 5 */
+2 -1
drivers/clk/tegra/clk-divider.c
··· 175 175 void __iomem *reg, spinlock_t *lock) 176 176 { 177 177 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, 179 180 mc_div_table, lock); 180 181 }
+35 -22
drivers/clk/tegra/clk-emc.c
··· 121 121 struct tegra_clk_emc *tegra; 122 122 u8 ram_code = tegra_read_ram_code(); 123 123 struct emc_timing *timing = NULL; 124 - int i; 124 + int i, k, t; 125 125 126 126 tegra = container_of(hw, struct tegra_clk_emc, hw); 127 127 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 + } 131 132 133 + for (t = k; t < tegra->num_timings; t++) { 134 + if (tegra->timings[t].ram_code != ram_code) 135 + break; 136 + } 137 + 138 + for (i = k; i < t; i++) { 132 139 timing = tegra->timings + i; 133 140 141 + if (timing->rate < req->rate && i != t - 1) 142 + continue; 143 + 134 144 if (timing->rate > req->max_rate) { 135 - i = max(i, 1); 145 + i = max(i, k + 1); 136 146 req->rate = tegra->timings[i - 1].rate; 137 147 return 0; 138 148 } ··· 150 140 if (timing->rate < req->min_rate) 151 141 continue; 152 142 153 - if (timing->rate >= req->rate) { 154 - req->rate = timing->rate; 155 - return 0; 156 - } 143 + req->rate = timing->rate; 144 + return 0; 157 145 } 158 146 159 147 if (timing) { ··· 222 214 223 215 if (emc_get_parent(&tegra->hw) == timing->parent_index && 224 216 clk_get_rate(timing->parent) != timing->parent_rate) { 225 - BUG(); 217 + WARN_ONCE(1, "parent %s rate mismatch %lu %lu\n", 218 + __clk_get_name(timing->parent), 219 + clk_get_rate(timing->parent), 220 + timing->parent_rate); 226 221 return -EINVAL; 227 222 } 228 223 ··· 293 282 for (i = timing_index+1; i < tegra->num_timings; i++) { 294 283 timing = tegra->timings + i; 295 284 if (timing->ram_code != ram_code) 296 - continue; 285 + break; 297 286 298 287 if (emc_parent_clk_sources[timing->parent_index] != 299 288 emc_parent_clk_sources[ ··· 304 293 for (i = timing_index-1; i >= 0; --i) { 305 294 timing = tegra->timings + i; 306 295 if (timing->ram_code != ram_code) 307 - continue; 296 + break; 308 297 309 298 if (emc_parent_clk_sources[timing->parent_index] != 310 299 emc_parent_clk_sources[ ··· 444 433 struct device_node *node, 445 434 u32 ram_code) 446 435 { 436 + struct emc_timing *timings_ptr; 447 437 struct device_node *child; 448 438 int child_count = of_get_child_count(node); 449 439 int i = 0, err; 440 + size_t size; 450 441 451 - tegra->timings = kcalloc(child_count, sizeof(struct emc_timing), 452 - GFP_KERNEL); 442 + size = (tegra->num_timings + child_count) * sizeof(struct emc_timing); 443 + 444 + tegra->timings = krealloc(tegra->timings, size, GFP_KERNEL); 453 445 if (!tegra->timings) 454 446 return -ENOMEM; 455 447 456 - tegra->num_timings = child_count; 448 + timings_ptr = tegra->timings + tegra->num_timings; 449 + tegra->num_timings += child_count; 457 450 458 451 for_each_child_of_node(node, child) { 459 - struct emc_timing *timing = tegra->timings + (i++); 452 + struct emc_timing *timing = timings_ptr + (i++); 460 453 461 454 err = load_one_timing_from_dt(tegra, timing, child); 462 455 if (err) { ··· 471 456 timing->ram_code = ram_code; 472 457 } 473 458 474 - sort(tegra->timings, tegra->num_timings, sizeof(struct emc_timing), 459 + sort(timings_ptr, child_count, sizeof(struct emc_timing), 475 460 cmp_timings, NULL); 476 461 477 462 return 0; ··· 514 499 * fuses until the apbmisc driver is loaded. 515 500 */ 516 501 err = load_timings_from_dt(tegra, node, node_ram_code); 517 - of_node_put(node); 518 - if (err) 502 + if (err) { 503 + of_node_put(node); 519 504 return ERR_PTR(err); 520 - break; 505 + } 521 506 } 522 507 523 508 if (tegra->num_timings == 0) ··· 546 531 547 532 /* Allow debugging tools to see the EMC clock */ 548 533 clk_register_clkdev(clk, "emc", "tegra-clk-debug"); 549 - 550 - clk_prepare_enable(clk); 551 534 552 535 return clk; 553 536 };
+39 -15
drivers/clk/tegra/clk-pll.c
··· 444 444 unsigned long flags = 0; 445 445 int ret; 446 446 447 + if (clk_pll_is_enabled(hw)) 448 + return 0; 449 + 447 450 if (pll->lock) 448 451 spin_lock_irqsave(pll->lock, flags); 449 452 ··· 666 663 pll_override_writel(val, params->pmc_divp_reg, pll); 667 664 668 665 val = pll_override_readl(params->pmc_divnm_reg, pll); 669 - val &= ~(divm_mask(pll) << div_nmp->override_divm_shift) | 670 - ~(divn_mask(pll) << div_nmp->override_divn_shift); 666 + val &= ~((divm_mask(pll) << div_nmp->override_divm_shift) | 667 + (divn_mask(pll) << div_nmp->override_divn_shift)); 671 668 val |= (cfg->m << div_nmp->override_divm_shift) | 672 669 (cfg->n << div_nmp->override_divn_shift); 673 670 pll_override_writel(val, params->pmc_divnm_reg, pll); ··· 943 940 static int clk_plle_enable(struct clk_hw *hw) 944 941 { 945 942 struct tegra_clk_pll *pll = to_clk_pll(hw); 946 - unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 947 943 struct tegra_clk_pll_freq_table sel; 944 + unsigned long input_rate; 948 945 u32 val; 949 946 int err; 947 + 948 + if (clk_pll_is_enabled(hw)) 949 + return 0; 950 + 951 + input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 950 952 951 953 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) 952 954 return -EINVAL; ··· 1363 1355 int ret; 1364 1356 unsigned long flags = 0; 1365 1357 1358 + if (clk_pll_is_enabled(hw)) 1359 + return 0; 1360 + 1366 1361 if (pll->lock) 1367 1362 spin_lock_irqsave(pll->lock, flags); 1368 1363 ··· 1578 1567 u32 val; 1579 1568 int ret; 1580 1569 unsigned long flags = 0; 1581 - unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 1570 + unsigned long input_rate; 1571 + 1572 + if (clk_pll_is_enabled(hw)) 1573 + return 0; 1574 + 1575 + input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 1582 1576 1583 1577 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) 1584 1578 return -EINVAL; ··· 1719 1703 pr_err("%s: failed to get OSC clock\n", __func__); 1720 1704 return -EINVAL; 1721 1705 } 1706 + 1707 + if (clk_pll_is_enabled(hw)) 1708 + return 0; 1722 1709 1723 1710 input_rate = clk_hw_get_rate(__clk_get_hw(osc)); 1724 1711 ··· 2398 2379 return clk; 2399 2380 } 2400 2381 2382 + static int clk_plle_tegra210_is_enabled(struct clk_hw *hw) 2383 + { 2384 + struct tegra_clk_pll *pll = to_clk_pll(hw); 2385 + u32 val; 2386 + 2387 + val = pll_readl_base(pll); 2388 + 2389 + return val & PLLE_BASE_ENABLE ? 1 : 0; 2390 + } 2391 + 2401 2392 static int clk_plle_tegra210_enable(struct clk_hw *hw) 2402 2393 { 2403 2394 struct tegra_clk_pll *pll = to_clk_pll(hw); ··· 2415 2386 u32 val; 2416 2387 int ret = 0; 2417 2388 unsigned long flags = 0; 2418 - unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 2389 + unsigned long input_rate; 2390 + 2391 + if (clk_plle_tegra210_is_enabled(hw)) 2392 + return 0; 2393 + 2394 + input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 2419 2395 2420 2396 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) 2421 2397 return -EINVAL; ··· 2529 2495 out: 2530 2496 if (pll->lock) 2531 2497 spin_unlock_irqrestore(pll->lock, flags); 2532 - } 2533 - 2534 - static int clk_plle_tegra210_is_enabled(struct clk_hw *hw) 2535 - { 2536 - struct tegra_clk_pll *pll = to_clk_pll(hw); 2537 - u32 val; 2538 - 2539 - val = pll_readl_base(pll); 2540 - 2541 - return val & PLLE_BASE_ENABLE ? 1 : 0; 2542 2498 } 2543 2499 2544 2500 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
+1 -2
drivers/clk/tegra/clk-tegra124.c
··· 413 413 .base_reg = PLLM_BASE, 414 414 .misc_reg = PLLM_MISC, 415 415 .lock_mask = PLL_BASE_LOCK, 416 - .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, 417 416 .lock_delay = 300, 418 417 .max_p = 5, 419 418 .pdiv_tohw = pllm_p, ··· 420 421 .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, 421 422 .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2, 422 423 .freq_table = pll_m_freq_table, 423 - .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, 424 + .flags = TEGRA_PLL_USE_LOCK, 424 425 }; 425 426 426 427 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+5 -2
include/dt-bindings/clock/stm32fx-clock.h
··· 54 54 #define CLK_I2C3 28 55 55 #define CLK_I2C4 29 56 56 #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 59 62 60 63 #endif
+79
include/linux/clk/analogbits-wrpll-cln28hpc.h
··· 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 */
+3 -9
include/linux/clk/at91_pmc.h
··· 74 74 #define AT91_PMC_USBDIV_4 (2 << 28) 75 75 #define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ 76 76 77 + #define AT91_PMC_CPU_CKR 0x28 /* CPU Clock Register */ 78 + 77 79 #define AT91_PMC_MCKR 0x30 /* Master Clock Register */ 78 80 #define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ 79 81 #define AT91_PMC_CSS_SLOW (0 << 0) ··· 189 187 190 188 #define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9 and SAMA5] */ 191 189 #define AT91_PMC_PCR_PID_MASK 0x3f 192 - #define AT91_PMC_PCR_GCKCSS_OFFSET 8 193 - #define AT91_PMC_PCR_GCKCSS_MASK (0x7 << AT91_PMC_PCR_GCKCSS_OFFSET) 194 - #define AT91_PMC_PCR_GCKCSS(n) ((n) << AT91_PMC_PCR_GCKCSS_OFFSET) /* GCK Clock Source Selection */ 195 190 #define AT91_PMC_PCR_CMD (0x1 << 12) /* Command (read=0, write=1) */ 196 - #define AT91_PMC_PCR_DIV_OFFSET 16 197 - #define AT91_PMC_PCR_DIV_MASK (0x3 << AT91_PMC_PCR_DIV_OFFSET) 198 - #define AT91_PMC_PCR_DIV(n) ((n) << AT91_PMC_PCR_DIV_OFFSET) /* Divisor Value */ 199 - #define AT91_PMC_PCR_GCKDIV_OFFSET 20 200 - #define AT91_PMC_PCR_GCKDIV_MASK (0xff << AT91_PMC_PCR_GCKDIV_OFFSET) 201 - #define AT91_PMC_PCR_GCKDIV(n) ((n) << AT91_PMC_PCR_GCKDIV_OFFSET) /* Generated Clock Divisor Value */ 191 + #define AT91_PMC_PCR_GCKDIV_MASK GENMASK(27, 20) 202 192 #define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ 203 193 #define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */ 204 194