Commit ca4e7c51 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull clk updates from Stephen Boyd:
 "The large diff this time around is from the addition of a new clk
  driver for the TI Davinci family of SoCs. So far those clks have been
  supported with a custom implementation of the clk API in the arch port
  instead of in the CCF. With this driver merged we're one step closer
  to having a single clk API implementation.

  The other large diff is from the Amlogic clk driver that underwent
  some major surgery to use regmap. Beyond that, the biggest hitter is
  Samsung which needed some reworks to properly handle clk provider
  power domains and a bunch of PLL rate updates.

  The core framework was fairly quiet this round, just getting some
  cleanups and small fixes for some of the more esoteric features. And
  the usual set of driver non-critical fixes, cleanups, and minor
  additions are here as well.

  Core:
   - Rejig clk_ops::init() to be a little earlier for phase/accuracy ops
   - debugfs ops macroized to shave some lines of boilerplate code
   - Always calculate the phase instead of caching it in clk_get_phase()
   - More __must_check on bulk clk APIs

  New Drivers:
   - TI's Davinci family of SoCs
   - Intel's Stratix10 SoC
   - stm32mp157 SoC
   - Allwinner H6 CCU
   - Silicon Labs SI544 clock generator chip
   - Renesas R-Car M3-N and V3H SoCs
   - i.MX6SLL SoCs

  Removed Drivers:
   - ST-Ericsson AB8540/9540

  Updates:
   - Mediatek MT2701 and MT7622 audsys support and MT2712 updates
   - STM32F469 DSI and STM32F769 sdmmc2 support
   - GPIO clks can sleep now
   - Spreadtrum SC9860 RTC clks
   - Nvidia Tegra MBIST workarounds and various minor fixes
   - Rockchip phase handling fixes and a memory leak plugged
   - Renesas drivers switch to readl/writel from clk_readl/clk_writel
   - Renesas gained CPU (Z/Z2) and watchdog support
   - Rockchip rk3328 display clks and rk3399 1.6GHz PLL support
   - Qualcomm PM8921 PMIC XO buffers
   - Amlogic migrates to regmap APIs
   - TI Keystone clk latching support
   - Allwinner H3 and H5 video clk fixes
   - Broadcom BCM2835 PLLs needed another bit to enable
   - i.MX6SX CKO mux fix and i.MX7D Video PLL divider fix
   - i.MX6UL/ULL epdc_podf support
   - Hi3798CV200 COMBPHY0 and USB2_OTG_UTMI and phase support for eMMC"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (233 commits)
  clk: davinci: add a reset lookup table for psc0
  clk: imx: add clock driver for imx6sll
  dt-bindings: imx: update clock doc for imx6sll
  clk: imx: add new gate/gate2 wrapper funtion
  clk: imx: Add CLK_IS_CRITICAL flag for busy divider and busy mux
  clk: cs2000: set pm_ops in hibernate-compatible way
  clk: bcm2835: De-assert/assert PLL reset signal when appropriate
  clk: imx7d: Move clks_init_on before any clock operations
  clk: imx7d: Correct ahb clk parent select
  clk: imx7d: Correct dram pll type
  clk: imx7d: Add USB clock information
  clk: socfpga: stratix10: add clock driver for Stratix10 platform
  dt-bindings: documentation: add clock bindings information for Stratix10
  clk: ti: fix flag space conflict with clkctrl clocks
  clk: uniphier: add additional ethernet clock lines for Pro4
  clk: uniphier: add SATA clock control support
  clk: uniphier: add PCIe clock control support
  clk: Add driver for the si544 clock generator chip
  clk: davinci: Remove redundant dev_err calls
  clk: uniphier: add ethernet clock control support for PXs3
  ...
parents daf3ef6e b44c4ddf
......@@ -268,9 +268,19 @@ The common clock framework uses two global locks, the prepare lock and the
enable lock.
The enable lock is a spinlock and is held across calls to the .enable,
.disable and .is_enabled operations. Those operations are thus not allowed to
sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API
functions are allowed in atomic context.
.disable operations. Those operations are thus not allowed to sleep,
and calls to the clk_enable(), clk_disable() API functions are allowed in
atomic context.
For clk_is_enabled() API, it is also designed to be allowed to be used in
atomic context. However, it doesn't really make any sense to hold the enable
lock in core, unless you want to do something else with the information of
the enable state with that lock held. Otherwise, seeing if a clk is enabled is
a one-shot read of the enabled state, which could just as easily change after
the function returns because the lock is released. Thus the user of this API
needs to handle synchronizing the read of the state with whatever they're
using it for to make sure that the enable state doesn't change during that
time.
The prepare lock is a mutex and is held across calls to all other operations.
All those operations are allowed to sleep, and calls to the corresponding API
......
......@@ -6,6 +6,7 @@ The MediaTek AUDSYS controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt7622-audsys", "syscon"
- #clock-cells: Must be 1
......@@ -13,10 +14,19 @@ The AUDSYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Required sub-nodes:
-------
For common binding part and usage, refer to
../sonud/mt2701-afe-pcm.txt.
Example:
audsys: audsys@11220000 {
compatible = "mediatek,mt7622-audsys", "syscon";
reg = <0 0x11220000 0 0x1000>;
#clock-cells = <1>;
};
audsys: clock-controller@11220000 {
compatible = "mediatek,mt7622-audsys", "syscon";
reg = <0 0x11220000 0 0x2000>;
#clock-cells = <1>;
afe: audio-controller {
...
};
};
* Clock bindings for Freescale i.MX6 SLL
Required properties:
- compatible: Should be "fsl,imx6sll-ccm"
- reg: Address and length of the register set
- #clock-cells: Should be <1>
- clocks: list of clock specifiers, must contain an entry for each required
entry in clock-names
- clock-names: should include entries "ckil", "osc", "ipp_di0" and "ipp_di1"
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx6sll-clock.h
for the full list of i.MX6 SLL clock IDs.
Examples:
#include <dt-bindings/clock/imx6sll-clock.h>
clks: clock-controller@20c4000 {
compatible = "fsl,imx6sll-ccm";
reg = <0x020c4000 0x4000>;
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
#clock-cells = <1>;
clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
};
uart1: serial@2020000 {
compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SLL_CLK_UART1_IPG>,
<&clks IMX6SLL_CLK_UART1_SERIAL>;
clock-names = "ipg", "per";
};
Device Tree Clock bindings for Intel's SoCFPGA Stratix10 platform
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : shall be
"intel,stratix10-clkmgr"
- reg : shall be the control register offset from CLOCK_MANAGER's base for the clock.
- #clock-cells : from common clock binding, shall be set to 1.
Example:
clkmgr: clock-controller@ffd10000 {
compatible = "intel,stratix10-clkmgr";
reg = <0xffd10000 0x1000>;
#clock-cells = <1>;
};
......@@ -22,7 +22,9 @@ Required Properties:
- "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2)
- "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
- "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
- "renesas,r8a77965-cpg-mssr" for the r8a77965 SoC (R-Car M3-N)
- "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M)
- "renesas,r8a77980-cpg-mssr" for the r8a77980 SoC (R-Car V3H)
- "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3)
- reg: Base address and length of the memory resource used by the CPG/MSSR
......@@ -32,8 +34,8 @@ Required Properties:
clock-names
- clock-names: List of external parent clock names. Valid names are:
- "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
r8a7795, r8a7796, r8a77970, r8a77995)
- "extalr" (r8a7795, r8a7796, r8a77970)
r8a7795, r8a7796, r8a77965, r8a77970, r8a77980, r8a77995)
- "extalr" (r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
- "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
- #clock-cells: Must be 2
......
......@@ -32,6 +32,7 @@ clock-output-names:
- "clkin_i2s" - external I2S clock - optional,
- "gmac_clkin" - external GMAC clock - optional
- "phy_50m_out" - output clock of the pll in the mac phy
- "hdmi_phy" - output clock of the hdmi phy pll - optional
Example: Clock controller node:
......
Binding for Silicon Labs 544 programmable I2C clock generator.
Reference
This binding uses the common clock binding[1]. Details about the device can be
found in the datasheet[2].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Si544 datasheet
https://www.silabs.com/documents/public/data-sheets/si544-datasheet.pdf
Required properties:
- compatible: One of "silabs,si514a", "silabs,si514b" "silabs,si514c" according
to the speed grade of the chip.
- reg: I2C device address.
- #clock-cells: From common clock bindings: Shall be 0.
Optional properties:
- clock-output-names: From common clock bindings. Recommended to be "si544".
Example:
si544: clock-controller@55 {
reg = <0x55>;
#clock-cells = <0>;
compatible = "silabs,si544b";
};
STMicroelectronics STM32 Peripheral Reset Clock Controller
==========================================================
The RCC IP is both a reset and a clock controller.
RCC makes also power management (resume/supend and wakeup interrupt).
Please also refer to reset.txt for common reset controller binding usage.
Please also refer to clock-bindings.txt for common clock controller
binding usage.
Required properties:
- compatible: "st,stm32mp1-rcc", "syscon"
- reg: should be register base and length as documented in the datasheet
- #clock-cells: 1, device nodes should specify the clock in their
"clocks" property, containing a phandle to the clock device node,
an index specifying the clock to use.
- #reset-cells: Shall be 1
- interrupts: Should contain a general interrupt line and a interrupt line
to the wake-up of processor (CSTOP).
Example:
rcc: rcc@50000000 {
compatible = "st,stm32mp1-rcc", "syscon";
reg = <0x50000000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>,
<GIC_SPI 145 IRQ_TYPE_NONE>;
};
Specifying clocks
=================
All available clocks are defined as preprocessor macros in
dt-bindings/clock/stm32mp1-clks.h header and can be used in device
tree sources.
Specifying softreset control of devices
=======================================
Device nodes should specify the reset channel required in their "resets"
property, containing a phandle to the reset device node and an index specifying
which channel to use.
The index is the bit number within the RCC registers bank, starting from RCC
base address.
It is calculated as: index = register_offset / 4 * 32 + bit_offset.
Where bit_offset is the bit offset within the register.
For example on STM32MP1, for LTDC reset:
ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset
= 0x180 / 4 * 32 + 0 = 3072
The list of valid indices for STM32MP1 is available in:
include/dt-bindings/reset-controller/stm32mp1-resets.h
This file implements defines like:
#define LTDC_R 3072
......@@ -20,6 +20,7 @@ Required properties :
- "allwinner,sun50i-a64-ccu"
- "allwinner,sun50i-a64-r-ccu"
- "allwinner,sun50i-h5-ccu"
- "allwinner,sun50i-h6-ccu"
- "nextthing,gr8-ccu"
- reg: Must contain the registers base address and length
......@@ -31,6 +32,9 @@ Required properties :
- #clock-cells : must contain 1
- #reset-cells : must contain 1
For the main CCU on H6, one more clock is needed:
- "iosc": the SoC's internal frequency oscillator
For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
- "pll-periph": the SoC's peripheral PLL from the main CCU
- "iosc": the SoC's internal frequency oscillator
......
Binding for TI DA8XX/OMAP-L13X/AM17XX/AM18XX CFGCHIP clocks
TI DA8XX/OMAP-L13X/AM17XX/AM18XX SoCs contain a general purpose set of
registers call CFGCHIPn. Some of these registers function as clock
gates. This document describes the bindings for those clocks.
All of the clock nodes described below must be child nodes of a CFGCHIP node
(compatible = "ti,da830-cfgchip").
USB PHY clocks
--------------
Required properties:
- compatible: shall be "ti,da830-usb-phy-clocks".
- #clock-cells: from common clock binding; shall be set to 1.
- clocks: phandles to the parent clocks corresponding to clock-names
- clock-names: shall be "fck", "usb_refclkin", "auxclk"
This node provides two clocks. The clock at index 0 is the USB 2.0 PHY 48MHz
clock and the clock at index 1 is the USB 1.1 PHY 48MHz clock.
eHRPWM Time Base Clock (TBCLK)
------------------------------
Required properties:
- compatible: shall be "ti,da830-tbclksync".
- #clock-cells: from common clock binding; shall be set to 0.
- clocks: phandle to the parent clock
- clock-names: shall be "fck"
PLL DIV4.5 divider
------------------
Required properties:
- compatible: shall be "ti,da830-div4p5ena".
- #clock-cells: from common clock binding; shall be set to 0.
- clocks: phandle to the parent clock
- clock-names: shall be "pll0_pllout"
EMIFA clock source (ASYNC1)
---------------------------
Required properties:
- compatible: shall be "ti,da850-async1-clksrc".
- #clock-cells: from common clock binding; shall be set to 0.
- clocks: phandles to the parent clocks corresponding to clock-names
- clock-names: shall be "pll0_sysclk3", "div4.5"
ASYNC3 clock source
-------------------
Required properties:
- compatible: shall be "ti,da850-async3-clksrc".
- #clock-cells: from common clock binding; shall be set to 0.
- clocks: phandles to the parent clocks corresponding to clock-names
- clock-names: shall be "pll0_sysclk2", "pll1_sysclk2"
Examples:
cfgchip: syscon@1417c {
compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
reg = <0x1417c 0x14>;
usb_phy_clk: usb-phy-clocks {
compatible = "ti,da830-usb-phy-clocks";
#clock-cells = <1>;
clocks = <&psc1 1>, <&usb_refclkin>, <&pll0_auxclk>;
clock-names = "fck", "usb_refclkin", "auxclk";
};
ehrpwm_tbclk: ehrpwm_tbclk {
compatible = "ti,da830-tbclksync";
#clock-cells = <0>;
clocks = <&psc1 17>;
clock-names = "fck";
};
div4p5_clk: div4.5 {
compatible = "ti,da830-div4p5ena";
#clock-cells = <0>;
clocks = <&pll0_pllout>;
clock-names = "pll0_pllout";
};
async1_clk: async1 {
compatible = "ti,da850-async1-clksrc";
#clock-cells = <0>;
clocks = <&pll0_sysclk 3>, <&div4p5_clk>;
clock-names = "pll0_sysclk3", "div4.5";
};
async3_clk: async3 {
compatible = "ti,da850-async3-clksrc";
#clock-cells = <0>;
clocks = <&pll0_sysclk 2>, <&pll1_sysclk 2>;
clock-names = "pll0_sysclk2", "pll1_sysclk2";
};
};
Also see:
- Documentation/devicetree/bindings/clock/clock-bindings.txt
Binding for TI DaVinci PLL Controllers
The PLL provides clocks to most of the components on the SoC. In addition
to the PLL itself, this controller also contains bypasses, gates, dividers,
an multiplexers for various clock signals.
Required properties:
- compatible: shall be one of:
- "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
- "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
- reg: physical base address and size of the controller's register area.
- clocks: phandles corresponding to the clock names
- clock-names: names of the clock sources - depends on compatible string
- for "ti,da850-pll0", shall be "clksrc", "extclksrc"
- for "ti,da850-pll1", shall be "clksrc"
Optional properties:
- ti,clkmode-square-wave: Indicates that the the board is supplying a square
wave input on the OSCIN pin instead of using a crystal oscillator.
This property is only valid when compatible = "ti,da850-pll0".
Optional child nodes:
pllout
Describes the main PLL clock output (before POSTDIV). The node name must
be "pllout".
Required properties:
- #clock-cells: shall be 0
sysclk
Describes the PLLDIVn divider clocks that provide the SYSCLKn clock
domains. The node name must be "sysclk". Consumers of this node should
use "n" in "SYSCLKn" as the index parameter for the clock cell.
Required properties:
- #clock-cells: shall be 1
auxclk
Describes the AUXCLK output of the PLL. The node name must be "auxclk".
This child node is only valid when compatible = "ti,da850-pll0".
Required properties:
- #clock-cells: shall be 0
obsclk
Describes the OBSCLK output of the PLL. The node name must be "obsclk".
Required properties:
- #clock-cells: shall be 0
Examples:
pll0: clock-controller@11000 {
compatible = "ti,da850-pll0";
reg = <0x11000 0x1000>;
clocks = <&ref_clk>, <&pll1_sysclk 3>;
clock-names = "clksrc", "extclksrc";
ti,clkmode-square-wave;
pll0_pllout: pllout {
#clock-cells = <0>;
};
pll0_sysclk: sysclk {
#clock-cells = <1>;
};
pll0_auxclk: auxclk {
#clock-cells = <0>;
};
pll0_obsclk: obsclk {
#clock-cells = <0>;
};
};
pll1: clock-controller@21a000 {
compatible = "ti,da850-pll1";
reg = <0x21a000 0x1000>;
clocks = <&ref_clk>;
clock-names = "clksrc";
pll0_sysclk: sysclk {
#clock-cells = <1>;
};
pll0_obsclk: obsclk {
#clock-cells = <0>;
};
};
Also see:
- Documentation/devicetree/bindings/clock/clock-bindings.txt
Binding for TI DaVinci Power Sleep Controller (PSC)
The PSC provides power management, clock gating and reset functionality. It is
primarily used for clocking.
Required properties:
- compatible: shall be one of:
- "ti,da850-psc0" for PSC0 on DA850/OMAP-L138/AM18XX
- "ti,da850-psc1" for PSC1 on DA850/OMAP-L138/AM18XX
- reg: physical base address and size of the controller's register area
- #clock-cells: from common clock binding; shall be set to 1
- #power-domain-cells: from generic power domain binding; shall be set to 1.
- clocks: phandles to clocks corresponding to the clock-names property
- clock-names: list of parent clock names - depends on compatible value
- for "ti,da850-psc0", shall be "pll0_sysclk1", "pll0_sysclk2",
"pll0_sysclk4", "pll0_sysclk6", "async1"
- for "ti,da850-psc1", shall be "pll0_sysclk2", "pll0_sysclk4", "async3"
Optional properties:
- #reset-cells: from reset binding; shall be set to 1 - only applicable when
at least one local domain provides a local reset.
Consumers:
Clock, power domain and reset consumers shall use the local power domain
module ID (LPSC) as the index corresponding to the clock cell. Refer to
the device-specific datasheet to find these numbers. NB: Most local
domains only provide a clock/power domain and not a reset.
Examples:
psc0: clock-controller@10000 {
compatible = "ti,da850-psc0";
reg = <0x10000 0x1000>;
#clock-cells = <1>;
#power-domain-cells = <1>;
#reset-cells = <1>;
clocks = <&pll0_sysclk 1>, <&pll0_sysclk 2>,
<&pll0_sysclk 4>, <&pll0_sysclk 6>, <&async1_clk>;
clock_names = "pll0_sysclk1", "pll0_sysclk2",
"pll0_sysclk4", "pll0_sysclk6", "async1";
};
psc1: clock-controller@227000 {
compatible = "ti,da850-psc1";
reg = <0x227000 0x1000>;
#clock-cells = <1>;
#power-domain-cells = <1>;
clocks = <&pll0_sysclk 2>, <&pll0_sysclk 4>, <&async3_clk>;
clock_names = "pll0_sysclk2", "pll0_sysclk4", "async3";
};
/* consumer */
dsp: dsp@11800000 {
compatible = "ti,da850-dsp";
reg = <0x11800000 0x40000>,
<0x11e00000 0x8000>,
<0x11f00000 0x8000>,
<0x01c14044 0x4>,
<0x01c14174 0x8>;
reg-names = "l2sram", "l1pram", "l1dram", "host1cfg", "chipsig";
interrupt-parent = <&intc>;
interrupts = <28>;
clocks = <&psc0 15>;
power-domains = <&psc0 15>;
resets = <&psc0 15>;
};
Also see:
- Documentation/devicetree/bindings/clock/clock-bindings.txt
- Documentation/devicetree/bindings/power/power_domain.txt
- Documentation/devicetree/bindings/reset/reset.txt
......@@ -75,6 +75,9 @@ Optional properties:
- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0,
see [2]
- ti,set-rate-parent : clk_set_rate is propagated to parent
- ti,latch-bit : latch the divider value to HW, only needed if the register
access requires this. As an example dra76x DPLL_GMAC H14 divider implements
such behavior.
Examples:
dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 {
......
......@@ -48,6 +48,9 @@ Optional properties:
zero
- ti,set-rate-parent : clk_set_rate is propagated to parent clock,
not supported by the composite-mux-clock subtype
- ti,latch-bit : latch the mux value to HW, only needed if the register
access requires this. As an example, dra7x DPLL_GMAC H14 muxing
implements such behavior.
Examples:
......
......@@ -12365,6 +12365,7 @@ M: Tomasz Figa <tomasz.figa@gmail.com>
M: Chanwoo Choi <cw00.choi@samsung.com>
S: Supported
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/snawrocki/clk.git
F: drivers/clk/samsung/
F: include/dt-bindings/clock/exynos*.h
F: Documentation/devicetree/bindings/clock/exynos*.txt
......@@ -14001,6 +14002,13 @@ F: arch/arm/mach-davinci/
F: drivers/i2c/busses/i2c-davinci.c
F: arch/arm/boot/dts/da850*
TI DAVINCI SERIES CLOCK DRIVER
M: David Lechner <david@lechnology.com>
R: Sekhar Nori <nsekhar@ti.com>
S: Maintained
F: Documentation/devicetree/bindings/clock/ti/davinci/
F: drivers/clk/davinci/
TI DAVINCI SERIES GPIO DRIVER
M: Keerthy <j-keerthy@ti.com>
L: linux-gpio@vger.kernel.org
......
......@@ -55,8 +55,10 @@ config COMMON_CLK_RK808
by control register.
config COMMON_CLK_HI655X
tristate "Clock driver for Hi655x"
depends on MFD_HI655X_PMIC || COMPILE_TEST
tristate "Clock driver for Hi655x" if EXPERT
depends on (MFD_HI655X_PMIC || COMPILE_TEST)
depends on REGMAP
default MFD_HI655X_PMIC
---help---
This driver supports the hi655x PMIC clock. This
multi-function device has one fixed-rate oscillator, clocked
......@@ -101,6 +103,15 @@ config COMMON_CLK_SI514
This driver supports the Silicon Labs 514 programmable clock
generator.
config COMMON_CLK_SI544
tristate "Clock driver for SiLabs 544 devices"
depends on I2C
select REGMAP_I2C
help
---help---
This driver supports the Silicon Labs 544 programmable clock
generator.
config COMMON_CLK_SI570
tristate "Clock driver for SiLabs 570 and compatible devices"
depends on I2C
......@@ -248,6 +259,26 @@ config COMMON_CLK_VC5
This driver supports the IDT VersaClock 5 and VersaClock 6
programmable clock generators.
config COMMON_CLK_STM32MP157
def_bool COMMON_CLK && MACH_STM32MP157
help
---help---
Support for stm32mp157 SoC family clocks
config COMMON_CLK_STM32F
bool "Clock driver for stm32f4 and stm32f7 SoC families"
depends on MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746
help
---help---
Support for stm32f4 and stm32f7 SoC families clocks
config COMMON_CLK_STM32H7
bool "Clock driver for stm32h7 SoC family"
depends on MACH_STM32H743
help
---help---
Support for stm32h7 SoC family clocks
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
......
......@@ -45,9 +45,11 @@ obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
obj-$(CONFIG_COMMON_CLK_SI544) += clk-si544.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
obj-$(CONFIG_ARCH_STM32) += clk-stm32h7.o
obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_U300) += clk-u300.o
......@@ -62,6 +64,7 @@ obj-$(CONFIG_ARCH_ARTPEC) += axis/
obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
obj-y += bcm/
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_H8300) += h8300/
obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-y += imgtec/
......@@ -89,6 +92,7 @@ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_SPRD) += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_STRATIX10) += socfpga/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
......
......@@ -602,9 +602,7 @@ static void bcm2835_pll_off(struct clk_hw *hw)
const struct bcm2835_pll_data *data = pll->data;
spin_lock(&cprman->regs_lock);
cprman_write(cprman, data->cm_ctrl_reg,
cprman_read(cprman, data->cm_ctrl_reg) |
CM_PLL_ANARST);
cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
cprman_write(cprman, data->a2w_ctrl_reg,
cprman_read(cprman, data->a2w_ctrl_reg) |
A2W_PLL_CTRL_PWRDN);
......@@ -640,6 +638,10 @@ static int bcm2835_pll_on(struct clk_hw *hw)
cpu_relax();
}
cprman_write(cprman, data->a2w_ctrl_reg,
cprman_read(cprman, data->a2w_ctrl_reg) |
A2W_PLL_CTRL_PRST_DISABLE);
return 0;
}
......
......@@ -549,7 +549,7 @@ static int cs2000_resume(struct device *dev)
}
static const struct dev_pm_ops cs2000_pm_ops = {
.resume_early = cs2000_resume,
SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, cs2000_resume)
};
static struct i2c_driver cs2000_driver = {
......
......@@ -28,12 +28,10 @@
* parent - fixed parent. No clk_set_parent support
*/
#define div_mask(width) ((1 << (width)) - 1)
static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
u8 width)
{
unsigned int maxdiv = 0, mask = div_mask(width);
unsigned int maxdiv = 0, mask = clk_div_mask(width);
const struct clk_div_table *clkt;
for (clkt = table; clkt->div; clkt++)
......@@ -57,12 +55,12 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
unsigned long flags)
{
if (flags & CLK_DIVIDER_ONE_BASED)
return div_mask(width);
return clk_div_mask(width);
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << div_mask(width);
return 1 << clk_div_mask(width);
if (table)
return _get_table_maxdiv(table, width);
return div_mask(width) + 1;
return clk_div_mask(width) + 1;
}
static unsigned int _get_table_div(const struct clk_div_table *table,
......@@ -84,7 +82,7 @@ static unsigned int _get_div(const struct clk_div_table *table,
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return 1 << val;
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return val ? val : div_mask(width) + 1;
return val ? val : clk_div_mask(width) + 1;
if (table)
return _get_table_div(table, val);
return val + 1;
......@@ -109,7 +107,7 @@ static unsigned int _get_val(const struct clk_div_table *table,
if (flags & CLK_DIVIDER_POWER_OF_TWO)
return __ffs(div);
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
return (div == div_mask(width) + 1) ? 0 : div;
return (div == clk_div_mask(width) + 1) ? 0 : div;
if (table)
return _get_table_val(table, div);
return div - 1;
......@@ -141,7 +139,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
unsigned int val;
val = clk_readl(divider->reg) >> divider->shift;
val &= div_mask(divider->width);
val &= clk_div_mask(divider->width);
return divider_recalc_rate(hw, parent_rate, val, divider->table,
divider->flags, divider->width);
......@@ -344,19 +342,43 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
}
EXPORT_SYMBOL_GPL(divider_round_rate_parent);
long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
unsigned long rate, unsigned long *prate,
const struct clk_div_table *table, u8 width,
unsigned long flags, unsigned int val)
{
int div;
div = _get_div(table, val, flags, width);
/* Even a read-only clock can propagate a rate change */
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
if (!parent)
return -EINVAL;
*prate = clk_hw_round_rate(parent, rate * div);
}
return DIV_ROUND_UP_ULL((u64)*prate, div);
}
EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_divider *divider = to_clk_divider(hw);
int bestdiv;
/* if read only, just return current value */
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
bestdiv = clk_readl(divider->reg) >> divider->shift;
bestdiv &= div_mask(divider->width);
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
divider->width);
return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
u32 val;
val = clk_readl(divider->reg) >> divider->shift;
val &= clk_div_mask(divider->width);
return divider_ro_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags,
val);
}
return divider_round_rate(hw, rate, prate, divider->table,
......@@ -376,7 +398,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
value = _get_val(table, div, flags, width);
return min_t(unsigned int, value, div_mask(width));
return min_t(unsigned int, value, clk_div_mask(width));
}
EXPORT_SYMBOL_GPL(divider_get_val);
......@@ -399,10 +421,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
__acquire(divider->lock);
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
val = div_mask(divider->width) << (divider->shift + 16);
val = clk_div_mask(divider->width) << (divider->shift + 16);
} else {
val = clk_readl(divider->reg);
val &= ~(div_mask(divider->width) << divider->shift);
val &= ~(clk_div_mask(divider->width) << divider->shift);
}
val |= (u32)value << divider->shift;
clk_writel(val, divider->reg);
......
......@@ -73,14 +73,14 @@ static u8 clk_gpio_mux_get_parent(struct clk_hw *hw)
{
struct clk_gpio *clk = to_clk_gpio(hw);
return gpiod_get_value(clk->gpiod);
return gpiod_get_value_cansleep(clk->gpiod);
}
static int clk_gpio_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_gpio *clk = to_clk_gpio(hw);
gpiod_set_value(clk->gpiod, index);
gpiod_set_value_cansleep(clk->gpiod, index);
return 0;
}
......
......@@ -26,35 +26,24 @@
* parent - parent is adjustable through clk_set_parent
*/
static u8 clk_mux_get_parent(struct clk_hw *hw)
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
unsigned int val)
{
struct clk_mux *mux = to_clk_mux(hw);
int num_parents = clk_hw_get_num_parents(hw);
u32 val;
/*
* FIXME need a mux-specific flag to determine if val is bitwise or numeric
* e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
* to 0x7 (index starts at one)
* OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
* val = 0x4 really means "bit 2, index starts at bit 0"
*/
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
if (mux->table) {
if (table) {
int i;
for (i = 0; i < num_parents; i++)
if (mux->table[i] == val)
if (table[i] == val)
return i;
return -EINVAL;
}
if (val && (mux->flags & CLK_MUX_INDEX_BIT))
if (val && (flags & CLK_MUX_INDEX_BIT))
val = ffs(val) - 1;
if (val && (mux->flags & CLK_MUX_INDEX_ONE))
if (val && (flags & CLK_MUX_INDEX_ONE))
val--;
if (val >= num_parents)
......@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
return val;
}
EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val;
unsigned long flags = 0;
unsigned int val = index;
if (mux->table) {
index = mux->table[index];
if (table) {
val = table[index];
} else {
if (mux->flags & CLK_MUX_INDEX_BIT)
index = 1 << index;
if (flags & CLK_MUX_INDEX_BIT)
val = 1 << index;
if (mux->flags & CLK_MUX_INDEX_ONE)
index++;
if (flags & CLK_MUX_INDEX_ONE)
val++;
}
return val;
}
EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
static u8 clk_mux_get_parent(struct clk_hw *hw)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val;
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
}
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
unsigned long flags = 0;
u32 reg;
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
else
__acquire(mux->lock);
if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16);
reg = mux->mask << (mux->shift + 16);
} else {
val = clk_readl(mux->reg);
val &= ~(mux->mask << mux->shift);
reg = clk_readl(mux->reg);
reg &= ~(mux->mask << mux->shift);
}
val |= index << mux->shift;
clk_writel(val, mux->reg);
val = val << mux->shift;
reg |= val;
clk_writel(reg, mux->reg);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Silicon Labs Si544 Programmable Oscillator
* Copyright (C) 2018 Topic Embedded Products
* Author: Mike Looijmans <mike.looijmans@topic.nl>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
/* I2C registers (decimal as in datasheet) */
#define SI544_REG_CONTROL 7
#define SI544_REG_OE_STATE 17
#define SI544_REG_HS_DIV 23
#define SI544_REG_LS_HS_DIV 24
#define SI544_REG_FBDIV0 26
#define SI544_REG_FBDIV8 27
#define SI544_REG_FBDIV16 28
#define SI544_REG_FBDIV24 29
#define SI544_REG_FBDIV32 30
#define SI544_REG_FBDIV40 31
#define SI544_REG_FCAL_OVR 69
#define SI544_REG_ADPLL_DELTA_M0 231
#define SI544_REG_ADPLL_DELTA_M8 232
#define SI544_REG_ADPLL_DELTA_M16 233
#define SI544_REG_PAGE_SELECT 255
/* Register values */
#define SI544_CONTROL_RESET BIT(7)
#define SI544_CONTROL_MS_ICAL2 BIT(3)
#define SI544_OE_STATE_ODC_OE BIT(0)
/* Max freq depends on speed grade */
#define SI544_MIN_FREQ 200000U
/* Si544 Internal oscilator runs at 55.05 MHz */
#define FXO 55050000U
/* VCO range is 10.8 .. 12.1 GHz, max depends on speed grade */
#define FVCO_MIN 10800000000ULL
#define HS_DIV_MAX 2046
#define HS_DIV_MAX_ODD 33
/* Lowest frequency synthesizeable using only the HS divider */
#define MIN_HSDIV_FREQ (FVCO_MIN / HS_DIV_MAX)
enum si544_speed_grade {
si544a,
si544b,
si544c,
};
struct clk_si544 {
struct clk_hw hw;
struct regmap *regmap;
struct i2c_client *i2c_client;
enum si544_speed_grade speed_grade;
};
#define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw)
/**
* struct clk_si544_muldiv - Multiplier/divider settings
* @fb_div_frac: integer part of feedback divider (32 bits)
* @fb_div_int: fractional part of feedback divider (11 bits)
* @hs_div: 1st divider, 5..2046, must be even when >33
* @ls_div_bits: 2nd divider, as 2^x, range 0..5
* If ls_div_bits is non-zero, hs_div must be even
*/
struct clk_si544_muldiv {
u32 fb_div_frac;
u16 fb_div_int;
u16 hs_div;
u8 ls_div_bits;
};
/* Enables or disables the output driver */
static int si544_enable_output(struct clk_si544 *data, bool enable)
{
return regmap_update_bits(data->regmap, SI544_REG_OE_STATE,
SI544_OE_STATE_ODC_OE, enable ? SI544_OE_STATE_ODC_OE : 0);
}
/* Retrieve clock multiplier and dividers from hardware */
static int si544_get_muldiv(struct clk_si544 *data,
struct clk_si544_muldiv *settings)
{
int err;
u8 reg[6];
err = regmap_bulk_read(data->regmap, SI544_REG_HS_DIV, reg, 2);
if (err)
return err;
settings->ls_div_bits = (reg[1] >> 4) & 0x07;
settings->hs_div = (reg[1] & 0x07) << 8 | reg[0];
err = regmap_bulk_read(data->regmap, SI544_REG_FBDIV0, reg, 6);
if (err)
return err;
settings->fb_div_int = reg[4] | (reg[5] & 0x07) << 8;
settings->fb_div_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
reg[3] << 24;
return 0;
}
static int si544_set_muldiv(struct clk_si544 *data,
struct clk_si544_muldiv *settings)
{
int err;
u8 reg[6];
reg[0] = settings->hs_div;
reg[1] = settings->hs_div >> 8 | settings->ls_div_bits << 4;
err = regmap_bulk_write(data->regmap, SI544_REG_HS_DIV, reg, 2);
if (err < 0)
return err;
reg[0] = settings->fb_div_frac;
reg[1] = settings->fb_div_frac >> 8;
reg[2] = settings->fb_div_frac >> 16;
reg[3] = settings->fb_div_frac >> 24;
reg[4] = settings->fb_div_int;
reg[5] = settings->fb_div_int >> 8;
/*
* Writing to SI544_REG_FBDIV40 triggers the clock change, so that
* must be written last
*/
return regmap_bulk_write(data->regmap, SI544_REG_FBDIV0, reg, 6);
}
static bool is_valid_frequency(const struct clk_si544 *data,
unsigned long frequency)
{
unsigned long max_freq = 0;
if (frequency < SI544_MIN_FREQ)
return false;
switch (data->speed_grade) {
case si544a:
max_freq = 1500000000;
break;
case si544b:
max_freq = 800000000;
break;
case si544c:
max_freq = 350000000;
break;
}
return frequency <= max_freq;
}
/* Calculate divider settings for a given frequency */
static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
unsigned long frequency)
{
u64 vco;
u32 ls_freq;
u32 tmp;
u8 res;
/* Determine the minimum value of LS_DIV and resulting target freq. */
ls_freq = frequency;
settings->ls_div_bits = 0;
if (frequency >= MIN_HSDIV_FREQ) {
settings->ls_div_bits = 0;
} else {
res = 1;
tmp = 2 * HS_DIV_MAX;
while (tmp <= (HS_DIV_MAX * 32)) {
if (((u64)frequency * tmp) >= FVCO_MIN)
break;
++res;
tmp <<= 1;
}
settings->ls_div_bits = res;
ls_freq = frequency << res;
}
/* Determine minimum HS_DIV by rounding up */
vco = FVCO_MIN + ls_freq - 1;
do_div(vco, ls_freq);
settings->hs_div = vco;
/* round up to even number when required */
if ((settings->hs_div & 1) &&
(settings->hs_div > HS_DIV_MAX_ODD || settings->ls_div_bits))
++settings->hs_div;
/* Calculate VCO frequency (in 10..12GHz range) */
vco = (u64)ls_freq * settings->hs_div;
/* Calculate the integer part of the feedback divider */
tmp = do_div(vco, FXO);
settings->fb_div_int = vco;
/* And the fractional bits using the remainder */
vco = (u64)tmp << 32;
do_div(vco, FXO);
settings->fb_div_frac = vco;
return 0;
}
/* Calculate resulting frequency given the register settings */
static unsigned long si544_calc_rate(struct clk_si544_muldiv *settings)
{
u32 d = settings->hs_div * BIT(settings->ls_div_bits);
u64 vco;
/* Calculate VCO from the fractional part */
vco = (u64)settings->fb_div_frac * FXO;
vco += (FXO / 2);
vco >>= 32;
/* Add the integer part of the VCO frequency */
vco += (u64)settings->fb_div_int * FXO;
/* Apply divider to obtain the generated frequency */
do_div(vco, d);
return vco;
}
static unsigned long si544_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_si544 *data = to_clk_si544(hw);
struct clk_si544_muldiv settings;
int err;
err = si544_get_muldiv(data, &settings);
if (err)
return 0;
return si544_calc_rate(&settings);
}
static long si544_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct clk_si544 *data = to_clk_si544(hw);
struct clk_si544_muldiv settings;
int err;
if (!is_valid_frequency(data, rate))
return -EINVAL;
err = si544_calc_muldiv(&settings, rate);
if (err)
return err;
return si544_calc_rate(&settings);
}
/*
* Update output frequency for "big" frequency changes
*/
static int si544_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_si544 *data = to_clk_si544(hw);
struct clk_si544_muldiv settings;
int err;
if (!is_valid_frequency(data, rate))
return -EINVAL;
err = si544_calc_muldiv(&settings, rate);
if (err)
return err;
si544_enable_output(data, false);
/* Allow FCAL for this frequency update */
err = regmap_write(data->regmap, SI544_REG_FCAL_OVR, 0);
if (err < 0)
return err;
err = si544_set_muldiv(data, &settings);
if (err < 0)
return err; /* Undefined state now, best to leave disabled */
/* Trigger calibration */
err = regmap_write(data->regmap, SI544_REG_CONTROL,
SI544_CONTROL_MS_ICAL2);
if (err < 0)
return err;
/* Applying a new frequency can take up to 10ms */
usleep_range(10000, 12000);
si544_enable_output(data, true);
return err;
}
static const struct clk_ops si544_clk_ops = {
.recalc_rate = si544_recalc_rate,
.round_rate = si544_round_rate,
.set_rate = si544_set_rate,
};
static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case SI544_REG_CONTROL:
case SI544_REG_FCAL_OVR:
return true;
default:
return false;
}
}
static const struct regmap_config si544_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.max_register = SI544_REG_PAGE_SELECT,
.volatile_reg = si544_regmap_is_volatile,
};
static int si544_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct clk_si544 *data;
struct clk_init_data init;
int err;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
init.ops = &si544_clk_ops;
init.flags = 0;
init.num_parents = 0;
data->hw.init = &init;
data->i2c_client = client;
data->speed_grade = id->driver_data;
if (of_property_read_string(client->dev.of_node, "clock-output-names",
&init.name))
init.name = client->dev.of_node->name;
data->regmap = devm_regmap_init_i2c(client, &si544_regmap_config);
if (IS_ERR(data->regmap))
return PTR_ERR(data->regmap);
i2c_set_clientdata(client, data);
/* Select page 0, just to be sure, there appear to be no more */
err = regmap_write(data->regmap, SI544_REG_PAGE_SELECT, 0);
if (err < 0)
return err;
err = devm_clk_hw_register(&client->dev, &data->hw);
if (err) {
dev_err(&client->dev, "clock registration failed\n");
return err;
}
err = devm_of_clk_add_hw_provider(&client->dev, of_clk_hw_simple_get,
&data->hw);
if (err) {
dev_err(&client->dev, "unable to add clk provider\n");
return err;
}
return 0;
}
static const struct i2c_device_id si544_id[] = {
{ "si544a", si544a },
{ "si544b", si544b },
{ "si544c", si544c },
{ }
};
MODULE_DEVICE_TABLE(i2c, si544_id);
static const struct of_device_id clk_si544_of_match[] = {
{ .compatible = "silabs,si544a" },
{ .compatible = "silabs,si544b" },
{ .compatible = "silabs,si544c" },
{ },
};
MODULE_DEVICE_TABLE(of, clk_si544_of_match);
static struct i2c_driver si544_driver = {
.driver = {
.name = "si544",
.of_match_table = clk_si544_of_match,
},
.probe = si544_probe,
.id_table = si544_id,
};
module_i2c_driver(si544_driver);
MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
MODULE_DESCRIPTION("Si544 driver");
MODULE_LICENSE("GPL");
......@@ -282,6 +282,7 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux" },
{ STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
......@@ -315,7 +316,7 @@ static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
0x0000000000000003ull,
0x04f77f033e01c9ffull };
0x04f77f833e01c9ffull };
static const u64 *stm32f4_gate_map;
......@@ -521,7 +522,7 @@ static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
};
static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
{ PLL, 50, { "pll", "pll-q", NULL } },
{ PLL, 50, { "pll", "pll-q", "pll-r" } },
{ PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
{ PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
};
......@@ -1047,6 +1048,8 @@ static const char *rtc_parents[4] = {
"no-clock", "lse", "lsi", "hse-rtc"
};
static const char *dsi_parent[2] = { NULL, "pll-r" };
static const char *lcd_parent[1] = { "pllsai-r-div" };
static const char *i2s_parents[2] = { "plli2s-r", NULL };
......@@ -1156,6 +1159,12 @@ static const struct stm32_aux_clk stm32f469_aux_clk[] = {
NO_GATE, 0,
0
},
{
CLK_F469_DSI, "dsi", dsi_parent, ARRAY_SIZE(dsi_parent),
STM32F4_RCC_DCKCFGR, 29, 1,
STM32F4_RCC_APB2ENR, 27,
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
},
};
static const struct stm32_aux_clk stm32f746_aux_clk[] = {
......@@ -1450,6 +1459,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
stm32f4_gate_map = data->gates_map;
hse_clk = of_clk_get_parent_name(np, 0);
dsi_parent[0] = hse_clk;
i2s_in_clk = of_clk_get_parent_name(np, 1);
......
This diff is collapsed.
......@@ -2375,6 +2375,9 @@ static int clk_core_get_phase(struct clk_core *core)
int ret;
clk_prepare_lock();
/* Always try to update cached phase if possible */
if (core->ops->get_phase)
core->phase = core->ops->get_phase(core->hw);
ret = core->phase;
clk_prepare_unlock();
......@@ -2491,19 +2494,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
return 0;
}
static int clk_summary_open(struct inode *inode, struct file *file)
{
return single_open(file, clk_summary_show, inode->i_private);
}
static const struct file_operations clk_summary_fops = {
.open = clk_summary_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(clk_summary);
static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
......@@ -2537,7 +2528,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
seq_putc(s, '}');
}
static int clk_dump(struct seq_file *s, void *data)
static int clk_dump_show(struct seq_file *s, void *data)
{
struct clk_core *c;
bool first_node = true;
......@@ -2560,19 +2551,7 @@ static int clk_dump(struct seq_file *s, void *data)
seq_puts(s, "}\n");
return 0;
}
static int clk_dump_open(struct inode *inode, struct file *file)
{
return single_open(file, clk_dump, inode->i_private);
}
static const struct file_operations clk_dump_fops = {
.open = clk_dump_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(clk_dump);
static const struct {
unsigned long flag;
......@@ -2594,7 +2573,7 @@ static const struct {
#undef ENTRY
};
static int clk_flags_dump(struct seq_file *s, void *data)
static int clk_flags_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
unsigned long flags = core->flags;
......@@ -2613,20 +2592,9 @@ static int clk_flags_dump(struct seq_file *s, void *data)
return 0;
}
DEFINE_SHOW_ATTRIBUTE(clk_flags);
static int clk_flags_open(struct inode *inode, struct file *file)
{
return single_open(file, clk_flags_dump, inode->i_private);
}
static const struct file_operations clk_flags_fops = {
.open = clk_flags_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int possible_parents_dump(struct seq_file *s, void *data)
static int possible_parents_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
int i;
......@@ -2638,18 +2606,7 @@ static int possible_parents_dump(struct seq_file *s, void *data)
return 0;
}
static int possible_parents_open(struct inode *inode, struct file *file)
{
return single_open(file, possible_parents_dump, inode->i_private);
}
static const struct file_operations possible_parents_fops = {
.open = possible_parents_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(possible_parents);
static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
......@@ -2932,6 +2889,17 @@ static int __clk_core_init(struct clk_core *core)
core->orphan = true;
}
/*
* optional platform-specific magic
*
* The .init callback is not used by any of the basic clock types, but
* exists for weird hardware that must perform initialization magic.
* Please consider other ways of solving initialization problems before
* using this callback, as its use is discouraged.
*/
if (core->ops->init)
core->ops->init(core->hw);
/*
* Set clk's accuracy. The preferred method is to use
* .recalc_accuracy. For simple clocks and lazy developers the default
......@@ -3009,17 +2977,6 @@ static int __clk_core_init(struct clk_core *core)
}
}
/*
* optional platform-specific magic
*
* The .init callback is not used by any of the basic clock types, but
* exists for weird hardware that must perform initialization magic.
* Please consider other ways of solving initialization problems before
* using this callback, as its use is discouraged.
*/
if (core->ops->init)
core->ops->init(core->hw);
kref_init(&core->ref);
out:
clk_pm_runtime_put(core);
......
# SPDX-License-Identifier: GPL-2.0
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx-cfgchip.o
obj-y += pll.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += pll-da830.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += pll-da850.o
obj-$(CONFIG_ARCH_DAVINCI_DM355) += pll-dm355.o
obj-$(CONFIG_ARCH_DAVINCI_DM365) += pll-dm365.o
obj-$(CONFIG_ARCH_DAVINCI_DM644x) += pll-dm644x.o
obj-$(CONFIG_ARCH_DAVINCI_DM646x) += pll-dm646x.o
obj-y += psc.o
obj-$(CONFIG_ARCH_DAVINCI_DA830) += psc-da830.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += psc-da850.o
obj-$(CONFIG_ARCH_DAVINCI_DM355) += psc-dm355.o
obj-$(CONFIG_ARCH_DAVINCI_DM365) += psc-dm365.o
obj-$(CONFIG_ARCH_DAVINCI_DM644x) += psc-dm644x.o
obj-$(CONFIG_ARCH_DAVINCI_DM646x) += psc-dm646x.o
endif
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* PLL clock descriptions for TI DA830/OMAP-L137/AM17XX
*
* Copyright (C) 2018 David Lechner <david@lechnology.com>
*/
#include <linux/clkdev.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/types.h>
#include "pll.h"
static const struct davinci_pll_clk_info da830_pll_info = {
.name = "pll0",
.pllm_mask = GENMASK(4, 0),
.pllm_min = 4,
.pllm_max = 32,
.pllout_min_rate = 300000000,
.pllout_max_rate = 600000000,
.flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
};
/*
* NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio",
* meaning that we could change the divider as long as we keep the correct
* ratio between all of the clocks, but we don't support that because there is
* currently not a need for it.
*/
SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0);
SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0);
SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0);
int da830_pll_init(struct device *dev, void __iomem *base)
{
struct clk *clk;
davinci_pll_clk_register(dev, &da830_pll_info, "ref_clk", base);
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base);
clk_register_clkdev(clk, "pll0_sysclk2", "da830-psc0");
clk_register_clkdev(clk, "pll0_sysclk2", "da830-psc1");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk3, base);
clk_register_clkdev(clk, "pll0_sysclk3", "da830-psc0");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk4, base);
clk_register_clkdev(clk, "pll0_sysclk4", "da830-psc0");
clk_register_clkdev(clk, "pll0_sysclk4", "da830-psc1");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk5, base);
clk_register_clkdev(clk, "pll0_sysclk5", "da830-psc1");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk6, base);
clk_register_clkdev(clk, "pll0_sysclk6", "da830-psc0");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk7, base);
clk = davinci_pll_auxclk_register(dev, "pll0_auxclk", base);
clk_register_clkdev(clk, NULL, "i2c_davinci.1");
clk_register_clkdev(clk, "timer0", NULL);
clk_register_clkdev(clk, NULL, "davinci-wdt");
return 0;
}
// SPDX-License-Identifier: GPL-2.0
/*
* PLL clock descriptions for TI DA850/OMAP-L138/AM18XX
*
* Copyright (C) 2018 David Lechner <david@lechnology.com>
*/
#include <linux/bitops.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/of.h>
#include <linux/types.h>
#include "pll.h"
#define OCSEL_OCSRC_OSCIN 0x14
#define OCSEL_OCSRC_PLL0_SYSCLK(n) (0x16 + (n))
#define OCSEL_OCSRC_PLL1_OBSCLK 0x1e
#define OCSEL_OCSRC_PLL1_SYSCLK(n) (0x16 + (n))
static const struct davinci_pll_clk_info da850_pll0_info = {
.name = "pll0",
.unlock_reg = CFGCHIP(0),
.unlock_mask = CFGCHIP0_PLL_MASTER_LOCK,
.pllm_mask = GENMASK(4, 0),
.pllm_min = 4,
.pllm_max = 32,
.pllout_min_rate = 300000000,
.pllout_max_rate = 600000000,
.flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV |
PLL_HAS_EXTCLKSRC,
};
/*
* NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio",
* meaning that we could change the divider as long as we keep the correct
* ratio between all of the clocks, but we don't support that because there is
* currently not a need for it.
*/
SYSCLK(1, pll0_sysclk1, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0);
SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0);
SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_ARM_RATE | SYSCLK_FIXED_DIV);
SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0);
static const char * const da850_pll0_obsclk_parent_names[] = {
"oscin",
"pll0_sysclk1",
"pll0_sysclk2",
"pll0_sysclk3",
"pll0_sysclk4",
"pll0_sysclk5",
"pll0_sysclk6",
"pll0_sysclk7",
"pll1_obsclk",
};
static u32 da850_pll0_obsclk_table[] = {
OCSEL_OCSRC_OSCIN,
OCSEL_OCSRC_PLL0_SYSCLK(1),
OCSEL_OCSRC_PLL0_SYSCLK(2),
OCSEL_OCSRC_PLL0_SYSCLK(3),
OCSEL_OCSRC_PLL0_SYSCLK(4),
OCSEL_OCSRC_PLL0_SYSCLK(5),
OCSEL_OCSRC_PLL0_SYSCLK(6),
OCSEL_OCSRC_PLL0_SYSCLK(7),
OCSEL_OCSRC_PLL1_OBSCLK,
};
static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info = {
.name = "pll0_obsclk",
.parent_names = da850_pll0_obsclk_parent_names,
.num_parents = ARRAY_SIZE(da850_pll0_obsclk_parent_names),
.table = da850_pll0_obsclk_table,
.ocsrc_mask = GENMASK(4, 0),
};
int da850_pll0_init(struct device *dev, void __iomem *base)
{
struct clk *clk;
davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base);
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk1, base);
clk_register_clkdev(clk, "pll0_sysclk1", "da850-psc0");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base);
clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc0");
clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc1");
clk_register_clkdev(clk, "pll0_sysclk2", "da850-async3-clksrc");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk3, base);
clk_register_clkdev(clk, "pll0_sysclk3", "da850-async1-clksrc");
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk4, base);
clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc0");
clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc1");
davinci_pll_sysclk_register(dev, &pll0_sysclk5, base);
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk6, base);
clk_register_clkdev(clk, "pll0_sysclk6", "da850-psc0");
davinci_pll_sysclk_register(dev, &pll0_sysclk7, base);
davinci_pll_auxclk_register(dev, "pll0_auxclk", base);
clk = clk_register_fixed_factor(dev, "async2", "pll0_auxclk",
CLK_IS_CRITICAL, 1, 1);
clk_register_clkdev(clk, NULL, "i2c_davinci.1");
clk_register_clkdev(clk, "timer0", NULL);
clk_register_clkdev(clk, NULL, "davinci-wdt");
davinci_pll_obsclk_register(dev, &da850_pll0_obsclk_info, base);
return 0;
}
static const struct davinci_pll_sysclk_info *da850_pll0_sysclk_info[] = {
&pll0_sysclk1,
&pll0_sysclk2,
&pll0_sysclk3,
&pll0_sysclk4,
&pll0_sysclk5,
&pll0_sysclk6,
&pll0_sysclk7,
NULL
};
int of_da850_pll0_init(struct device *dev, void __iomem *base)
{
return of_davinci_pll_init(dev, &da850_pll0_info,
&da850_pll0_obsclk_info,
da850_pll0_sysclk_info, 7, base);
}
static const struct davinci_pll_clk_info da850_pll1_info = {
.name = "pll1",
.unlock_reg = CFGCHIP(3),
.unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK,
.pllm_mask = GENMASK(4, 0),
.pllm_min = 4,
.pllm_max = 32,
.pllout_min_rate = 300000000,
.pllout_max_rate = 600000000,
.flags = PLL_HAS_POSTDIV,
};
SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, 0);
SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, 0);
static const char * const da850_pll1_obsclk_parent_names[] = {
"oscin",
"pll1_sysclk1",
"pll1_sysclk2",
"pll1_sysclk3",
};
static u32 da850_pll1_obsclk_table[] = {
OCSEL_OCSRC_OSCIN,
OCSEL_OCSRC_PLL1_SYSCLK(1),
OCSEL_OCSRC_PLL1_SYSCLK(2),
OCSEL_OCSRC_PLL1_SYSCLK(3),
};
static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info = {
.name = "pll1_obsclk",
.parent_names = da850_pll1_obsclk_parent_names,
.num_parents = ARRAY_SIZE(da850_pll1_obsclk_parent_names),
.table = da850_pll1_obsclk_table,
.ocsrc_mask = GENMASK(4, 0),
};
int da850_pll1_init(struct device *dev, void __iomem *base)
{
struct clk *clk;
davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base);
davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
clk_register_clkdev(clk, "pll1_sysclk2", "da850-async3-clksrc");
davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
davinci_pll_obsclk_register(dev, &da850_pll1_obsclk_info, base);
return 0;
}
static const struct davinci_pll_sysclk_info *da850_pll1_sysclk_info[] = {
&pll1_sysclk1,
&pll1_sysclk2,
&pll1_sysclk3,
NULL
};
int of_da850_pll1_init(struct device *dev, void __iomem *base)
{
return of_davinci_pll_init(dev, &da850_pll1_info,
&da850_pll1_obsclk_info,
da850_pll1_sysclk_info, 3, base);
}
// SPDX-License-Identifier: GPL-2.0
/*
* PLL clock descriptions for TI DM355
*
* Copyright (C) 2018 David Lechner <david@lechnology.com>
*/
#include <linux/bitops.h>
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/types.h>
#include "pll.h"
static const struct davinci_pll_clk_info dm355_pll1_info = {
.name = "pll1",
.pllm_mask = GENMASK(7, 0),
.pllm_min = 92,
.pllm_max = 184,
.flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_PREDIV_ALWAYS_ENABLED |
PLL_PREDIV_FIXED8 | PLL_HAS_POSTDIV |
PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV,
};
SYSCLK(1, pll1_sysclk1, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll1_sysclk2, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll1_sysclk3, pll1, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll1_sysclk4, pll1, 5, SYSCLK_ALWAYS_ENABLED);
int dm355_pll1_init(struct device *dev, void __iomem *base)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm355_pll1_info, "ref_clk", base);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk_register_clkdev(clk, "pll1_sysclk1", "dm355-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
clk_register_clkdev(clk, "pll1_sysclk2", "dm355-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
clk_register_clkdev(clk, "pll1_sysclk3", "dm355-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk4, base);
clk_register_clkdev(clk, "pll1_sysclk4", "dm355-psc");
clk = davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
clk_register_clkdev(clk, "pll1_auxclk", "dm355-psc");
davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);
return 0;
}
static const struct davinci_pll_clk_info dm355_pll2_info = {
.name = "pll2",
.pllm_mask = GENMASK(7, 0),
.pllm_min = 92,
.pllm_max = 184,
.flags = PLL_HAS_PREDIV | PLL_PREDIV_ALWAYS_ENABLED | PLL_HAS_POSTDIV |
PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV,
};
SYSCLK(1, pll2_sysclk1, pll2, 5, SYSCLK_FIXED_DIV);
SYSCLK(2, pll2_sysclk2, pll2, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
int dm355_pll2_init(struct device *dev, void __iomem *base)
{
davinci_pll_clk_register(dev, &dm355_pll2_info, "oscin", base);
davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
davinci_pll_sysclkbp_clk_register(dev, "pll2_sysclkbp", base);
return 0;
}
// SPDX-License-Identifier: GPL-2.0
/*
* PLL clock descriptions for TI DM365
*
* Copyright (C) 2018 David Lechner <david@lechnology.com>
*/
#include <linux/bitops.h>
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include "pll.h"
#define OCSEL_OCSRC_ENABLE 0
static const struct davinci_pll_clk_info dm365_pll1_info = {
.name = "pll1",
.pllm_mask = GENMASK(9, 0),
.pllm_min = 1,
.pllm_max = 1023,
.flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV |
PLL_POSTDIV_ALWAYS_ENABLED | PLL_PLLM_2X,
};
SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll1_sysclk4, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(5, pll1_sysclk5, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(6, pll1_sysclk6, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(7, pll1_sysclk7, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(8, pll1_sysclk8, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(9, pll1_sysclk9, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
/*
* This is a bit of a hack to make OCSEL[OCSRC] on DM365 look like OCSEL[OCSRC]
* on DA850. On DM365, OCSEL[OCSRC] is just an enable/disable bit instead of a
* multiplexer. By modeling it as a single parent mux clock, the clock code will
* still do the right thing in this case.
*/
static const char * const dm365_pll_obsclk_parent_names[] = {
"oscin",
};
static u32 dm365_pll_obsclk_table[] = {
OCSEL_OCSRC_ENABLE,
};
static const struct davinci_pll_obsclk_info dm365_pll1_obsclk_info = {
.name = "pll1_obsclk",
.parent_names = dm365_pll_obsclk_parent_names,
.num_parents = ARRAY_SIZE(dm365_pll_obsclk_parent_names),
.table = dm365_pll_obsclk_table,
.ocsrc_mask = BIT(4),
};
int dm365_pll1_init(struct device *dev, void __iomem *base)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk_register_clkdev(clk, "pll1_sysclk1", "dm365-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
clk_register_clkdev(clk, "pll1_sysclk2", "dm365-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
clk_register_clkdev(clk, "pll1_sysclk3", "dm365-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk4, base);
clk_register_clkdev(clk, "pll1_sysclk4", "dm365-psc");
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk5, base);
clk_register_clkdev(clk, "pll1_sysclk5", "dm365-psc");
davinci_pll_sysclk_register(dev, &pll1_sysclk6, base);
davinci_pll_sysclk_register(dev, &pll1_sysclk7, base);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk8, base);
clk_register_clkdev(clk, "pll1_sysclk8", "dm365-psc");
davinci_pll_sysclk_register(dev, &pll1_sysclk9, base);
clk = davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
clk_register_clkdev(clk, "pll1_auxclk", "dm355-psc");
davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);
davinci_pll_obsclk_register(dev, &dm365_pll1_obsclk_info, base);
return 0;
}
static const struct davinci_pll_clk_info dm365_pll2_info = {
.name = "pll2",
.pllm_mask = GENMASK(9, 0),
.pllm_min = 1,
.pllm_max = 1023,
.flags = PLL_HAS_PREDIV | PLL_HAS_POSTDIV | PLL_POSTDIV_ALWAYS_ENABLED |
PLL_PLLM_2X,
};
SYSCLK(1, pll2_sysclk1, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll2_sysclk2, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll2_sysclk3, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll2_sysclk4, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(5, pll2_sysclk5, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
static const struct davinci_pll_obsclk_info dm365_pll2_obsclk_info = {
.name = "pll2_obsclk",
.parent_names = dm365_pll_obsclk_parent_names,
.num_parents = ARRAY_SIZE(dm365_pll_obsclk_parent_names),
.table = dm365_pll_obsclk_table,
.ocsrc_mask = BIT(4),
};
int dm365_pll2_init(struct device *dev, void __iomem *base)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base);
davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
clk = davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
clk_register_clkdev(clk, "pll1_sysclk2", "dm365-psc");
davinci_pll_sysclk_register(dev, &pll2_sysclk3, base);
clk = davinci_pll_sysclk_register(dev, &pll2_sysclk4, base);
clk_register_clkdev(clk, "pll1_sysclk4", "dm365-psc");
davinci_pll_sysclk_register(dev, &pll2_sysclk5, base);
davinci_pll_auxclk_register(dev, "pll2_auxclk", base);
davinci_pll_obsclk_register(dev, &dm365_pll2_obsclk_info, base);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -3,7 +3,7 @@
# Hisilicon Clock specific Makefile
#
obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o
obj-y += clk.o clkgate-separated.o clkdivider-hi6220.o clk-hisi-phase.o
obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o
obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o
......
This diff is collapsed.
......@@ -49,6 +49,8 @@ struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
return NULL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return NULL;
clk_data->base = devm_ioremap(&pdev->dev,
res->start, resource_size(res));
if (!clk_data->base)
......@@ -197,6 +199,30 @@ int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
}
EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
int hisi_clk_register_phase(struct device *dev,
const struct hisi_phase_clock *clks,
int nums, struct hisi_clock_data *data)
{
void __iomem *base = data->base;
struct clk *clk;
int i;
for (i = 0; i < nums; i++) {
clk = clk_register_hisi_phase(dev, &clks[i], base,
&hisi_clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
clks[i].name);
return PTR_ERR(clk);
}
data->clk_data.clks[clks[i].id] = clk;
}
return 0;
}
EXPORT_SYMBOL_GPL(hisi_clk_register_phase);
int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
int nums, struct hisi_clock_data *data)
{
......
This diff is collapsed.
......@@ -204,7 +204,7 @@ static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
/* hi3516CV300 sysctrl CRG */
#define HI3516CV300_SYSCTRL_NR_CLKS 16
static const char *wdt_mux_p[] __initconst = { "3m", "apb" };
static const char *const wdt_mux_p[] __initconst = { "3m", "apb" };
static u32 wdt_mux_table[] = {0, 1};
static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
......
This diff is collapsed.
......@@ -22,6 +22,7 @@ obj-$(CONFIG_SOC_IMX35) += clk-imx35.o
obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -308,7 +308,10 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_SAI2_PODF] = imx_clk_divider("sai2_podf", "sai2_pred", base + 0x2c, 0, 6);
clks[IMX6UL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
clks[IMX6UL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
clks[IMX6UL_CLK_SIM_PODF] = imx_clk_divider("sim_podf", "sim_pre_sel", base + 0x34, 12, 3);
if (clk_on_imx6ul())
clks[IMX6UL_CLK_SIM_PODF] = imx_clk_divider("sim_podf", "sim_pre_sel", base + 0x34, 12, 3);
else if (clk_on_imx6ull())
clks[IMX6ULL_CLK_EPDC_PODF] = imx_clk_divider("epdc_podf", "epdc_pre_sel", base + 0x34, 12, 3);
clks[IMX6UL_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6);
clks[IMX6UL_CLK_LCDIF_PRED] = imx_clk_divider("lcdif_pred", "lcdif_pre_sel", base + 0x38, 12, 3);
clks[IMX6UL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment