Commit 3879ae65 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 core framework has a handful of patches this time around, mostly
  due to the clk rate protection support added by Jerome Brunet.

  This feature will allow consumers to lock in a certain rate on the
  output of a clk so that things like audio playback don't hear pops
  when the clk frequency changes due to shared parent clks changing
  rates. Currently the clk API doesn't guarantee the rate of a clk stays
  at the rate you request after clk_set_rate() is called, so this new
  API will allow drivers to express that requirement.

  Beyond this, the core got some debugfs pretty printing patches and a
  couple minor non-critical fixes.

  Looking outside of the core framework diff we have some new driver
  additions and the removal of a legacy TI clk driver. Both of these hit
  high in the dirstat. Also, the removal of the asm-generic/clkdev.h
  file causes small one-liners in all the architecture Kbuild files.

  Overall, the driver diff seems to be the normal stuff that comes all
  the time to fix little problems here and there and to support new
  hardware.

  Summary:

  Core:
   - Clk rate protection
   - Symbolic clk flags in debugfs output
   - Clk registration enabled clks while doing bookkeeping updates

  New Drivers:
   - Spreadtrum SC9860
   - HiSilicon hi3660 stub
   - Qualcomm A53 PLL, SPMI clkdiv, and MSM8916 APCS
   - Amlogic Meson-AXG
   - ASPEED BMC

  Removed Drivers:
   - TI OMAP 3xxx legacy clk (non-DT) support
   - asm*/clkdev.h got removed (not really a driver)

  Updates:
   - Renesas FDP1-0 module clock on R-Car M3-W
   - Renesas LVDS module clock on R-Car V3M
   - Misc fixes to pr_err() prints
   - Qualcomm MSM8916 audio fixes
   - Qualcomm IPQ8074 rounded out support for more peripherals
   - Qualcomm Alpha PLL variants
   - Divider code was using container_of() on bad pointers
   - Allwinner DE2 clks on H3
   - Amlogic minor data fixes and dropping of CLK_IGNORE_UNUSED
   - Mediatek clk driver compile test support
   - AT91 PMC clk suspend/resume restoration support
   - PLL issues fixed on si5351
   - Broadcom IProc PLL calculation updates
   - DVFS support for Armada mvebu CPU clks
   - Allwinner fixed post-divider support
   - TI clkctrl fixes and support for newer SoCs"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (125 commits)
  clk: aspeed: Handle inverse polarity of USB port 1 clock gate
  clk: aspeed: Fix return value check in aspeed_cc_init()
  clk: aspeed: Add reset controller
  clk: aspeed: Register gated clocks
  clk: aspeed: Add platform driver and register PLLs
  clk: aspeed: Register core clocks
  clk: Add clock driver for ASPEED BMC SoCs
  clk: mediatek: adjust dependency of reset.c to avoid unexpectedly being built
  clk: fix reentrancy of clk_enable() on UP systems
  clk: meson-axg: fix potential NULL dereference in axg_clkc_probe()
  clk: Simplify debugfs registration
  clk: Fix debugfs_create_*() usage
  clk: Show symbolic clock flags in debugfs
  clk: renesas: r8a7796: Add FDP clock
  clk: Move __clk_{get,put}() into private clk.h API
  clk: sunxi: Use CLK_IS_CRITICAL flag for critical clks
  clk: Improve flags doc for of_clk_detect_critical()
  arch: Remove clkdev.h asm-generic from Kbuild
  clk: sunxi-ng: a83t: Add M divider to TCON1 clock
  clk: Prepare to remove asm-generic/clkdev.h
  ...
parents fe53d144 c43a52cf
......@@ -13,12 +13,18 @@ Required Properties:
- "hisilicon,hi3660-pmuctrl"
- "hisilicon,hi3660-sctrl"
- "hisilicon,hi3660-iomcu"
- "hisilicon,hi3660-stub-clk"
- reg: physical base address of the controller and length of memory mapped
region.
- #clock-cells: should be 1.
Optional Properties:
- mboxes: Phandle to the mailbox for sending message to MCU.
(See: ../mailbox/hisilicon,hi3660-mailbox.txt for more info)
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
......
Qualcomm MSM8916 A53 PLL Binding
--------------------------------
The A53 PLL on MSM8916 platforms is the main CPU PLL used used for frequencies
above 1GHz.
Required properties :
- compatible : Shall contain only one of the following:
"qcom,msm8916-a53pll"
- reg : shall contain base register location and length
- #clock-cells : must be set to <0>
Example:
a53pll: clock@b016000 {
compatible = "qcom,msm8916-a53pll";
reg = <0xb016000 0x40>;
#clock-cells = <0>;
};
Qualcomm Technologies, Inc. SPMI PMIC clock divider (clkdiv)
clkdiv configures the clock frequency of a set of outputs on the PMIC.
These clocks are typically wired through alternate functions on
gpio pins.
=======================
Properties
=======================
- compatible
Usage: required
Value type: <string>
Definition: must be "qcom,spmi-clkdiv".
- reg
Usage: required
Value type: <prop-encoded-array>
Definition: base address of CLKDIV peripherals.
- qcom,num-clkdivs
Usage: required
Value type: <u32>
Definition: number of CLKDIV peripherals.
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the xo clock.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "xo".
- #clock-cells:
Usage: required
Value type: <u32>
Definition: shall contain 1.
=======
Example
=======
pm8998_clk_divs: clock-controller@5b00 {
compatible = "qcom,spmi-clkdiv";
reg = <0x5b00>;
#clock-cells = <1>;
qcom,num-clkdivs = <3>;
clocks = <&xo_board>;
clock-names = "xo";
assigned-clocks = <&pm8998_clk_divs 1>,
<&pm8998_clk_divs 2>,
<&pm8998_clk_divs 3>;
assigned-clock-rates = <9600000>,
<9600000>,
<9600000>;
};
......@@ -78,6 +78,7 @@ second cell is the clock index for the specified type.
2 hwaccel index (n in CLKCGnHWACSR)
3 fman 0 for fm1, 1 for fm2
4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4
4=pll/5, 5=pll/6, 6=pll/7, 7=pll/8
5 coreclk must be 0
3. Example
......
......@@ -49,6 +49,7 @@ Optional child node properties:
- silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth
divider.
- silabs,pll-master: boolean, multisynth can change pll frequency.
- silabs,pll-reset: boolean, clock output can reset its pll.
- silabs,disable-state : clock output disable state, shall be
0 = clock output is driven LOW when disabled
1 = clock output is driven HIGH when disabled
......
Spreadtrum Clock Binding
------------------------
Required properties:
- compatible: should contain the following compatible strings:
- "sprd,sc9860-pmu-gate"
- "sprd,sc9860-pll"
- "sprd,sc9860-ap-clk"
- "sprd,sc9860-aon-prediv"
- "sprd,sc9860-apahb-gate"
- "sprd,sc9860-aon-gate"
- "sprd,sc9860-aonsecure-clk"
- "sprd,sc9860-agcp-gate"
- "sprd,sc9860-gpu-clk"
- "sprd,sc9860-vsp-clk"
- "sprd,sc9860-vsp-gate"
- "sprd,sc9860-cam-clk"
- "sprd,sc9860-cam-gate"
- "sprd,sc9860-disp-clk"
- "sprd,sc9860-disp-gate"
- "sprd,sc9860-apapb-gate"
- #clock-cells: must be 1
- clocks : Should be the input parent clock(s) phandle for the clock, this
property here just simply shows which clock group the clocks'
parents are in, since each clk node would represent many clocks
which are defined in the driver. The detailed dependency
relationship (i.e. how many parents and which are the parents)
are implemented in driver code.
Optional properties:
- reg: Contain the registers base address and length. It must be configured
only if no 'sprd,syscon' under the node.
- sprd,syscon: phandle to the syscon which is in the same address area with
the clock, and so we can get regmap for the clocks from the
syscon device.
Example:
pmu_gate: pmu-gate {
compatible = "sprd,sc9860-pmu-gate";
sprd,syscon = <&pmu_regs>;
clocks = <&ext_26m>;
#clock-cells = <1>;
};
pll: pll {
compatible = "sprd,sc9860-pll";
sprd,syscon = <&ana_regs>;
clocks = <&pmu_gate 0>;
#clock-cells = <1>;
};
ap_clk: clock-controller@20000000 {
compatible = "sprd,sc9860-ap-clk";
reg = <0 0x20000000 0 0x400>;
clocks = <&ext_26m>, <&pll 0>,
<&pmu_gate 0>;
#clock-cells = <1>;
};
......@@ -4,13 +4,14 @@ Allwinner Display Engine 2.0 Clock Control Binding
Required properties :
- compatible: must contain one of the following compatibles:
- "allwinner,sun8i-a83t-de2-clk"
- "allwinner,sun8i-h3-de2-clk"
- "allwinner,sun8i-v3s-de2-clk"
- "allwinner,sun50i-h5-de2-clk"
- reg: Must contain the registers base address and length
- clocks: phandle to the clocks feeding the display engine subsystem.
Three are needed:
- "mod": the display engine module clock
- "mod": the display engine module clock (on A83T it's the DE PLL)
- "bus": the bus clock for the whole display engine subsystem
- clock-names: Must contain the clock names described just above
- resets: phandle to the reset control for the display engine subsystem.
......@@ -19,7 +20,7 @@ Required properties :
Example:
de2_clocks: clock@1000000 {
compatible = "allwinner,sun8i-a83t-de2-clk";
compatible = "allwinner,sun8i-h3-de2-clk";
reg = <0x01000000 0x100000>;
clocks = <&ccu CLK_BUS_DE>,
<&ccu CLK_DE>;
......
# SPDX-License-Identifier: GPL-2.0
generic-y += clkdev.h
generic-y += exec.h
generic-y += export.h
generic-y += fb.h
......
# SPDX-License-Identifier: GPL-2.0
generic-y += bugs.h
generic-y += clkdev.h
generic-y += device.h
generic-y += div64.h
generic-y += emergency-restart.h
......
generic-y += clkdev.h
generic-y += current.h
generic-y += early_ioremap.h
generic-y += emergency-restart.h
......
......@@ -105,6 +105,7 @@ config ARCH_MESON
select PINCTRL_MESON
select COMMON_CLK_AMLOGIC
select COMMON_CLK_GXBB
select COMMON_CLK_AXG
select MESON_IRQ_GPIO
help
This enables support for the Amlogic S905 SoCs.
......
generic-y += bugs.h
generic-y += clkdev.h
generic-y += delay.h
generic-y += div64.h
generic-y += dma.h
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_CLKDEV__H_
#define __ASM_CLKDEV__H_
#include <linux/slab.h>
static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
{
return kzalloc(size, GFP_KERNEL);
}
#ifndef CONFIG_COMMON_CLK
#define __clk_put(clk)
#define __clk_get(clk) ({ 1; })
#endif
#endif
generic-y += atomic.h
generic-y += barrier.h
generic-y += bugs.h
generic-y += clkdev.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
......
generic-y += atomic.h
generic-y += barrier.h
generic-y += clkdev.h
generic-y += cmpxchg.h
generic-y += current.h
generic-y += device.h
......
generic-y += clkdev.h
generic-y += device.h
generic-y += exec.h
generic-y += extable.h
......
......@@ -3,7 +3,6 @@ generic-y += barrier.h
generic-y += bugs.h
generic-y += cacheflush.h
generic-y += checksum.h
generic-y += clkdev.h
generic-y += current.h
generic-y += delay.h
generic-y += device.h
......
......@@ -2,7 +2,6 @@
generic-y += barrier.h
generic-y += bug.h
generic-y += bugs.h
generic-y += clkdev.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
......
generic-y += clkdev.h
generic-y += exec.h
generic-y += irq_work.h
generic-y += mcs_spinlock.h
......
generic-y += clkdev.h
generic-y += current.h
generic-y += dma-mapping.h
generic-y += exec.h
......
generic-y += barrier.h
generic-y += clkdev.h
generic-y += device.h
generic-y += emergency-restart.h
generic-y += exec.h
......
generic-y += bugs.h
generic-y += clkdev.h
generic-y += current.h
generic-y += device.h
generic-y += dma.h
......
......@@ -2,7 +2,6 @@ generic-y += barrier.h
generic-y += bitops.h
generic-y += bug.h
generic-y += bugs.h
generic-y += clkdev.h
generic-y += device.h
generic-y += div64.h
generic-y += emergency-restart.h
......
# MIPS headers
generic-(CONFIG_GENERIC_CSUM) += checksum.h
generic-y += clkdev.h
generic-y += current.h
generic-y += dma-contiguous.h
generic-y += emergency-restart.h
......
generic-y += barrier.h
generic-y += clkdev.h
generic-y += device.h
generic-y += exec.h
generic-y += extable.h
......
......@@ -3,7 +3,6 @@ generic-y += barrier.h
generic-y += bitops.h
generic-y += bug.h
generic-y += bugs.h
generic-y += clkdev.h
generic-y += cmpxchg.h
generic-y += current.h
generic-y += device.h
......
......@@ -2,7 +2,6 @@ generic-y += barrier.h
generic-y += bug.h
generic-y += bugs.h
generic-y += checksum.h
generic-y += clkdev.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
......
generic-y += barrier.h
generic-y += clkdev.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
......
generic-y += clkdev.h
generic-y += div64.h
generic-y += export.h
generic-y += irq_regs.h
......
generic-y += bugs.h
generic-y += cacheflush.h
generic-y += checksum.h
generic-y += clkdev.h
generic-y += cputime.h
generic-y += device.h
generic-y += div64.h
......
......@@ -6,7 +6,6 @@ generated-y += unistd_nr.h
generic-y += asm-offsets.h
generic-y += cacheflush.h
generic-y += clkdev.h
generic-y += device.h
generic-y += dma-contiguous.h
generic-y += dma-mapping.h
......
generic-y += barrier.h
generic-y += clkdev.h
generic-y += current.h
generic-y += extable.h
generic-y += irq_work.h
......
generic-y += clkdev.h
generic-y += current.h
generic-y += delay.h
generic-y += div64.h
......
# User exported sparc header files
generic-y += clkdev.h
generic-y += div64.h
generic-y += emergency-restart.h
generic-y += exec.h
......
generic-y += bug.h
generic-y += bugs.h
generic-y += clkdev.h
generic-y += emergency-restart.h
generic-y += exec.h
generic-y += extable.h
......
generic-y += barrier.h
generic-y += bpf_perf_event.h
generic-y += bug.h
generic-y += clkdev.h
generic-y += current.h
generic-y += delay.h
generic-y += device.h
......
generic-y += atomic.h
generic-y += bugs.h
generic-y += clkdev.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
......
......@@ -6,7 +6,6 @@ generated-y += unistd_32_ia32.h
generated-y += unistd_64_x32.h
generated-y += xen-hypercalls.h
generic-y += clkdev.h
generic-y += dma-contiguous.h
generic-y += early_ioremap.h
generic-y += mcs_spinlock.h
......
generic-y += bug.h
generic-y += clkdev.h
generic-y += device.h
generic-y += div64.h
generic-y += dma-contiguous.h
......
......@@ -142,6 +142,18 @@ config COMMON_CLK_GEMINI
This driver supports the SoC clocks on the Cortina Systems Gemini
platform, also known as SL3516 or CS3516.
config COMMON_CLK_ASPEED
bool "Clock driver for Aspeed BMC SoCs"
depends on ARCH_ASPEED || COMPILE_TEST
default ARCH_ASPEED
select MFD_SYSCON
select RESET_CONTROLLER
---help---
This driver supports the SoC clocks on the Aspeed BMC platforms.
The G4 and G5 series, including the ast2400 and ast2500, are supported
by this driver.
config COMMON_CLK_S2MPS11
tristate "Clock driver for S2MPS1X/S5M8767 MFD"
depends on MFD_SEC_CORE || COMPILE_TEST
......@@ -236,6 +248,7 @@ source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sprd/Kconfig"
source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
......
......@@ -27,6 +27,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
obj-$(CONFIG_COMMON_CLK_ASPEED) += clk-aspeed.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
......@@ -67,7 +68,7 @@ obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_MACH_INGENIC) += ingenic/
obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
obj-$(CONFIG_MACH_LOONGSON32) += loongson1/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-y += mediatek/
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/
obj-$(CONFIG_MACH_PIC32) += microchip/
ifeq ($(CONFIG_COMMON_CLK), y)
......@@ -85,6 +86,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_ARCH_SIRF) += sirf/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_SPRD) += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/
......
......@@ -204,6 +204,8 @@ at91_clk_register_programmable(struct regmap *regmap,
if (ret) {
kfree(prog);
hw = ERR_PTR(ret);
} else {
pmc_register_pck(id);
}
return hw;
......
......@@ -22,6 +22,7 @@
#include "pmc.h"
#define PMC_MAX_IDS 128
#define PMC_MAX_PCKS 8
int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range)
......@@ -50,6 +51,7 @@ EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
static struct regmap *pmcreg;
static u8 registered_ids[PMC_MAX_IDS];
static u8 registered_pcks[PMC_MAX_PCKS];
static struct
{
......@@ -66,8 +68,13 @@ static struct
u32 pcr[PMC_MAX_IDS];
u32 audio_pll0;
u32 audio_pll1;
u32 pckr[PMC_MAX_PCKS];
} pmc_cache;
/*
* As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
* without alteration in the table, and 0 is for unused clocks.
*/
void pmc_register_id(u8 id)
{
int i;
......@@ -82,11 +89,30 @@ void pmc_register_id(u8 id)
}
}
/*
* As Programmable Clock 0 is valid on AT91 chips, there is an offset
* of 1 between the stored value and the real clock ID.
*/
void pmc_register_pck(u8 pck)
{
int i;
for (i = 0; i < PMC_MAX_PCKS; i++) {
if (registered_pcks[i] == 0) {
registered_pcks[i] = pck + 1;
break;
}
if (registered_pcks[i] == (pck + 1))
break;
}
}
static int pmc_suspend(void)
{
int i;
u8 num;
regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.scsr);
regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr);
regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
......@@ -103,14 +129,29 @@ static int pmc_suspend(void)
regmap_read(pmcreg, AT91_PMC_PCR,
&pmc_cache.pcr[registered_ids[i]]);
}
for (i = 0; registered_pcks[i]; i++) {
num = registered_pcks[i] - 1;
regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]);
}
return 0;
}
static bool pmc_ready(unsigned int mask)
{
unsigned int status;
regmap_read(pmcreg, AT91_PMC_SR, &status);
return ((status & mask) == mask) ? 1 : 0;
}
static void pmc_resume(void)
{
int i, ret = 0;
int i;
u8 num;
u32 tmp;
u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
if (pmc_cache.mckr != tmp)
......@@ -119,7 +160,7 @@ static void pmc_resume(void)
if (pmc_cache.pllar != tmp)
pr_warn("PLLAR was not configured properly by the firmware\n");
regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.scsr);
regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr);
regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
......@@ -133,14 +174,16 @@ static void pmc_resume(void)
pmc_cache.pcr[registered_ids[i]] |
AT91_PMC_PCR_CMD);
}
if (pmc_cache.uckr & AT91_PMC_UPLLEN) {
ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp,
!(tmp & AT91_PMC_LOCKU),
10, 5000);
if (ret)
pr_crit("USB PLL didn't lock when resuming\n");
for (i = 0; registered_pcks[i]; i++) {
num = registered_pcks[i] - 1;
regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
}
if (pmc_cache.uckr & AT91_PMC_UPLLEN)
mask |= AT91_PMC_LOCKU;
while (!pmc_ready(mask))
cpu_relax();
}
static struct syscore_ops pmc_syscore_ops = {
......
......@@ -31,8 +31,10 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
#ifdef CONFIG_PM
void pmc_register_id(u8 id);
void pmc_register_pck(u8 pck);
#else
static inline void pmc_register_id(u8 id) {}
static inline void pmc_register_pck(u8 pck) {}
#endif
#endif /* __PMC_H_ */
......@@ -269,23 +269,10 @@ static void __init cygnus_asiu_init(struct device_node *node)
}
CLK_OF_DECLARE(cygnus_asiu_clk, "brcm,cygnus-asiu-clk", cygnus_asiu_init);
/*
* AUDIO PLL VCO frequency parameter table
*
* PLL output frequency = ((ndiv_int + ndiv_frac / 2^20) *
* (parent clock rate / pdiv)
*
* On Cygnus, parent is the 25MHz oscillator
*/
static const struct iproc_pll_vco_param audiopll_vco_params[] = {
/* rate (Hz) ndiv_int ndiv_frac pdiv */
{ 1354750204UL, 54, 199238, 1 },
{ 1769470191UL, 70, 816639, 1 },
};
static const struct iproc_pll_ctrl audiopll = {
.flags = IPROC_CLK_PLL_NEEDS_SW_CFG | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_PLL_USER_MODE_ON | IPROC_CLK_PLL_RESET_ACTIVE_LOW,
IPROC_CLK_PLL_USER_MODE_ON | IPROC_CLK_PLL_RESET_ACTIVE_LOW |
IPROC_CLK_PLL_CALC_PARAM,
.reset = RESET_VAL(0x5c, 0, 1),
.dig_filter = DF_VAL(0x48, 0, 3, 6, 4, 3, 3),
.sw_ctrl = SW_CTRL_VAL(0x4, 0),
......@@ -300,8 +287,7 @@ static const struct iproc_pll_ctrl audiopll = {
static const struct iproc_clk_ctrl audiopll_clk[] = {
[BCM_CYGNUS_AUDIOPLL_CH0] = {
.channel = BCM_CYGNUS_AUDIOPLL_CH0,
.flags = IPROC_CLK_AON |
IPROC_CLK_MCLK_DIV_BY_2,
.flags = IPROC_CLK_AON | IPROC_CLK_MCLK_DIV_BY_2,
.enable = ENABLE_VAL(0x14, 8, 10, 9),
.mdiv = REG_VAL(0x14, 0, 8),
},
......@@ -321,9 +307,8 @@ static const struct iproc_clk_ctrl audiopll_clk[] = {
static void __init cygnus_audiopll_clk_init(struct device_node *node)
{
iproc_pll_clk_setup(node, &audiopll, audiopll_vco_params,
ARRAY_SIZE(audiopll_vco_params), audiopll_clk,
ARRAY_SIZE(audiopll_clk));
iproc_pll_clk_setup(node, &audiopll, NULL, 0,
audiopll_clk, ARRAY_SIZE(audiopll_clk));
}
CLK_OF_DECLARE(cygnus_audiopll, "brcm,cygnus-audiopll",
cygnus_audiopll_clk_init);
This diff is collapsed.
......@@ -80,6 +80,11 @@
*/
#define IPROC_CLK_PLL_RESET_ACTIVE_LOW BIT(9)
/*
* Calculate the PLL parameters are runtime, instead of using table
*/
#define IPROC_CLK_PLL_CALC_PARAM BIT(10)
/*
* Parameters for VCO frequency configuration
*
......
This diff is collapsed.
......@@ -40,6 +40,10 @@
#define MMCM_REG_FILTER1 0x4e
#define MMCM_REG_FILTER2 0x4f
#define MMCM_CLKOUT_NOCOUNT BIT(6)
#define MMCM_CLK_DIV_NOCOUNT BIT(12)
struct axi_clkgen {
void __iomem *base;
struct clk_hw clk_hw;
......@@ -298,13 +302,17 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned int d, m, dout;
unsigned long long tmp;
axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
if (d == 0 || dout == 0 || m == 0)
return -EINVAL;
return *parent_rate / d * m / dout;
tmp = (unsigned long long)*parent_rate * m;
tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
return min_t(unsigned long long, tmp, LONG_MAX);
}
static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
......@@ -315,18 +323,33 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
unsigned int reg;
unsigned long long tmp;
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, &reg);
if (reg & MMCM_CLKOUT_NOCOUNT) {
dout = 1;
} else {
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
}
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
if (reg & MMCM_CLK_DIV_NOCOUNT)
d = 1;
else
d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, &reg);
if (reg & MMCM_CLKOUT_NOCOUNT) {
m = 1;
} else {
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
}
if (d == 0 || dout == 0)
return 0;
tmp = (unsigned long long)(parent_rate / d) * m;
do_div(tmp, dout);
tmp = (unsigned long long)parent_rate * m;
tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d);
return min_t(unsigned long long, tmp, ULONG_MAX);
}
......
......@@ -118,12 +118,11 @@ static unsigned int _get_val(const struct clk_div_table *table,
unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
unsigned int val,
const struct clk_div_table *table,
unsigned long flags)
unsigned long flags, unsigned long width)
{
struct clk_divider *divider = to_clk_divider(hw);
unsigned int div;
div = _get_div(table, val, flags, divider->width);
div = _get_div(table, val, flags, width);
if (!div) {
WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
......@@ -145,7 +144,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
val &= div_mask(divider->width);
return divider_recalc_rate(hw, parent_rate, val, divider->table,
divider->flags);
divider->flags, divider->width);
}
static bool _is_valid_table_div(const struct clk_div_table *table,
......
......@@ -41,7 +41,7 @@ struct clockgen_pll_div {
};
struct clockgen_pll {
struct clockgen_pll_div div[4];
struct clockgen_pll_div div[8];
};
#define CLKSEL_VALID 1
......@@ -1127,6 +1127,13 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
struct clk *clk;
int ret;
/*
* For platform PLL, there are 8 divider clocks.
* For core PLL, there are 4 divider clocks at most.
*/
if (idx != PLATFORM_PLL && i >= 4)
break;
snprintf(pll->div[i].name, sizeof(pll->div[i].name),
"cg-pll%d-div%d", idx, i + 1);
......
......@@ -72,7 +72,7 @@ static const char * const si5351_input_names[] = {
"xtal", "clkin"
};
static const char * const si5351_pll_names[] = {
"plla", "pllb", "vxco"
"si5351_plla", "si5351_pllb", "si5351_vxco"
};
static const char * const si5351_msynth_names[] = {
"ms0", "ms1", "ms2", "ms3", "ms4", "ms5", "ms6", "ms7"
......@@ -903,13 +903,42 @@ static int _si5351_clkout_set_disable_state(
return 0;
}
static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num)
{
u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + num);
switch (val & SI5351_CLK_INPUT_MASK) {
case SI5351_CLK_INPUT_XTAL:
case SI5351_CLK_INPUT_CLKIN:
return; /* pll not used, no need to reset */
}
si5351_reg_write(drvdata, SI5351_PLL_RESET,
val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
SI5351_PLL_RESET_A);
dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n",
__func__, clk_hw_get_name(&drvdata->clkout[num].hw),
(val & SI5351_CLK_PLL_SELECT) ? 1 : 0);
}
static int si5351_clkout_prepare(struct clk_hw *hw)
{
struct si5351_hw_data *hwdata =
container_of(hw, struct si5351_hw_data, hw);
struct si5351_platform_data *pdata =
hwdata->drvdata->client->dev.platform_data;
si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
SI5351_CLK_POWERDOWN, 0);
/*
* Do a pll soft reset on the parent pll -- needed to get a
* deterministic phase relationship between the output clocks.
*/
if (pdata->clkout[hwdata->num].pll_reset)
_si5351_clkout_reset_pll(hwdata->drvdata, hwdata->num);
si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL,
(1 << hwdata->num), 0);
return 0;
......@@ -1297,6 +1326,9 @@ static int si5351_dt_parse(struct i2c_client *client,
pdata->clkout[num].pll_master =
of_property_read_bool(child, "silabs,pll-master");
pdata->clkout[num].pll_reset =
of_property_read_bool(child, "silabs,pll-reset");
}
client->dev.platform_data = pdata;
......@@ -1437,11 +1469,6 @@ static int si5351_i2c_probe(struct i2c_client *client,
}
}
if (!IS_ERR(drvdata->pxtal))
clk_prepare_enable(drvdata->pxtal);
if (!IS_ERR(drvdata->pclkin))
clk_prepare_enable(drvdata->pclkin);
/* register xtal input clock gate */
memset(&init, 0, sizeof(init));
init.name = si5351_input_names[0];
......@@ -1456,7 +1483,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
ret = devm_clk_hw_register(&client->dev, &drvdata->xtal);
if (ret) {
dev_err(&client->dev, "unable to register %s\n", init.name);
goto err_clk;
return ret;
}
/* register clkin input clock gate */
......@@ -1474,7 +1501,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (ret) {
dev_err(&client->dev, "unable to register %s\n",
init.name);
goto err_clk;
return ret;
}
}
......@@ -1496,7 +1523,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
ret = devm_clk_hw_register(&client->dev, &drvdata->pll[0].hw);
if (ret) {
dev_err(&client->dev, "unable to register %s\n", init.name);
goto err_clk;
return ret;
}
/* register PLLB or VXCO (Si5351B) */
......@@ -1520,7 +1547,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
ret = devm_clk_hw_register(&client->dev, &drvdata->pll[1].hw);
if (ret) {
dev_err(&client->dev, "unable to register %s\n", init.name);
goto err_clk;
return ret;
}
/* register clk multisync and clk out divider */
......@@ -1539,7 +1566,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (WARN_ON(!drvdata->msynth || !drvdata->clkout)) {
ret = -ENOMEM;
goto err_clk;
return ret;
}
for (n = 0; n < num_clocks; n++) {
......@@ -1559,7 +1586,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (ret) {
dev_err(&client->dev, "unable to register %s\n",
init.name);
goto err_clk;
return ret;
}
}
......@@ -1587,7 +1614,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
if (ret) {
dev_err(&client->dev, "unable to register %s\n",
init.name);
goto err_clk;
return ret;
}
/* set initial clkout rate */
......@@ -1606,17 +1633,17 @@ static int si5351_i2c_probe(struct i2c_client *client,
drvdata);
if (ret) {
dev_err(&client->dev, "unable to add clk provider\n");
goto err_clk;
return ret;
}
return 0;
}
err_clk:
if (!IS_ERR(drvdata->pxtal))
clk_disable_unprepare(drvdata->pxtal);
if (!IS_ERR(drvdata->pclkin))
clk_disable_unprepare(drvdata->pclkin);
return ret;
static int si5351_i2c_remove(struct i2c_client *client)
{
of_clk_del_provider(client->dev.of_node);
return 0;
}
static const struct i2c_device_id si5351_i2c_ids[] = {
......@@ -1634,6 +1661,7 @@ static struct i2c_driver si5351_driver = {
.of_match_table = of_match_ptr(si5351_dt_ids),
},
.probe = si5351_i2c_probe,
.remove = si5351_i2c_remove,
.id_table = si5351_i2c_ids,
};
module_i2c_driver(si5351_driver);
......
......@@ -1424,7 +1424,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
base = of_iomap(np, 0);
if (!base) {
pr_err("%s: unable to map resource", np->name);
pr_err("%s: unable to map resource\n", np->name);
return;
}
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) Gabriel Fernandez 2017
* Author: Gabriel Fernandez <gabriel.fernandez@st.com>
*
* License terms: GPL V2.0.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
* Copyright (C) STMicroelectronics 2017
* Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
*/
#include <linux/clk.h>
......
This diff is collapsed.
......@@ -20,6 +20,8 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
const char *con_id);
void __clk_free_clk(struct clk *clk);
int __clk_get(struct clk *clk);
void __clk_put(struct clk *clk);
#else
/* All these casts to avoid ifdefs in clkdev... */
static inline struct clk *
......@@ -32,5 +34,7 @@ static struct clk_hw *__clk_get_hw(struct clk *clk)
{
return (struct clk_hw *)clk;
}
static inline int __clk_get(struct clk *clk) { return 1; }
static inline void __clk_put(struct clk *clk) { }
#endif
......@@ -256,7 +256,7 @@ vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt,
{
struct clk_lookup_alloc *cla;
cla = __clkdev_alloc(sizeof(*cla));
cla = kzalloc(sizeof(*cla), GFP_KERNEL);
if (!cla)
return NULL;
......
......@@ -24,13 +24,13 @@ static void __init h8300_div_clk_setup(struct device_node *node)
num_parents = of_clk_get_parent_count(node);
if (!num_parents) {
pr_err("%s: no parent found", clk_name);
pr_err("%s: no parent found\n", clk_name);
return;
}
divcr = of_iomap(node, 0);
if (divcr == NULL) {
pr_err("%s: failed to map divide register", clk_name);
pr_err("%s: failed to map divide register\n", clk_name);
goto error;
}
offset = (unsigned long)divcr & 3;
......
......@@ -93,7 +93,7 @@ static void __init h8s2678_pll_clk_setup(struct device_node *node)
num_parents = of_clk_get_parent_count(node);
if (!num_parents) {
pr_err("%s: no parent found", clk_name);
pr_err("%s: no parent found\n", clk_name);
return;
}
......@@ -104,13 +104,13 @@ static void __init h8s2678_pll_clk_setup(struct device_node *node)
pll_clock->sckcr = of_iomap(node, 0);
if (pll_clock->sckcr == NULL) {
pr_err("%s: failed to map divide register", clk_name);
pr_err("%s: failed to map divide register\n", clk_name);
goto free_clock;
}
pll_clock->pllcr = of_iomap(node, 1);
if (pll_clock->pllcr == NULL) {
pr_err("%s: failed to map multiply register", clk_name);
pr_err("%s: failed to map multiply register\n", clk_name);
goto unmap_sckcr;
}
......
......@@ -49,3 +49,9 @@ config STUB_CLK_HI6220
default ARCH_HISI
help
Build the Hisilicon Hi6220 stub clock driver.
config STUB_CLK_HI3660
bool "Hi3660 Stub Clock Driver"
depends on COMMON_CLK_HI3660 && MAILBOX
help
Build the Hisilicon Hi3660 stub clock driver.
......@@ -15,3 +15,4 @@ obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
obj-$(CONFIG_RESET_HISI) += reset.o
obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o
obj-$(CONFIG_STUB_CLK_HI3660) += clk-hi3660-stub.o
/*
* Hisilicon clock driver
*
* Copyright (c) 2013-2017 Hisilicon Limited.
* Copyright (c) 2017 Linaro Limited.
*
* Author: Kai Zhao <zhaokai1@hisilicon.com>
* Tao Wang <kevin.wangtao@hisilicon.com>
* Leo Yan <leo.yan@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/hi3660-clock.h>
#define HI3660_STUB_CLOCK_DATA (0x70)
#define MHZ (1000 * 1000)
#define DEFINE_CLK_STUB(_id, _cmd, _name) \
{ \
.id = (_id), \
.cmd = (_cmd), \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = &hi3660_stub_clk_ops, \
.num_parents = 0, \
.flags = CLK_GET_RATE_NOCACHE, \
}, \
},
#define to_stub_clk(_hw) container_of(_hw, struct hi3660_stub_clk, hw)
struct hi3660_stub_clk_chan {
struct mbox_client cl;
struct mbox_chan *mbox;
};
struct hi3660_stub_clk {
unsigned int id;
struct clk_hw hw;
unsigned int cmd;
unsigned int msg[8];
unsigned int rate;
};
static void __iomem *freq_reg;
static struct hi3660_stub_clk_chan stub_clk_chan;
static unsigned long hi3660_stub_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct hi3660_stub_clk *stub_clk = to_stub_clk(hw);
/*
* LPM3 writes back the CPU frequency in shared SRAM so read
* back the frequency.
*/
stub_clk->rate = readl(freq_reg + (stub_clk->id << 2)) * MHZ;
return stub_clk->rate;
}
static long hi3660_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
/*
* LPM3 handles rate rounding so just return whatever
* rate is requested.
*/
return rate;
}
static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct hi3660_stub_clk *stub_clk = to_stub_clk(hw);
stub_clk->msg[0] = stub_clk->cmd;
stub_clk->msg[1] = rate / MHZ;
dev_dbg(stub_clk_chan.cl.dev, "set rate msg[0]=0x%x msg[1]=0x%x\n",
stub_clk->msg[0], stub_clk->msg[1]);
mbox_send_message(stub_clk_chan.mbox, stub_clk->msg);
mbox_client_txdone(stub_clk_chan.mbox, 0);
stub_clk->rate = rate;
return 0;
}
static const struct clk_ops hi3660_stub_clk_ops = {
.recalc_rate = hi3660_stub_clk_recalc_rate,
.round_rate = hi3660_stub_clk_round_rate,
.set_rate = hi3660_stub_clk_set_rate,
};
static struct hi3660_stub_clk hi3660_stub_clks[HI3660_CLK_STUB_NUM] = {
DEFINE_CLK_STUB(HI3660_CLK_STUB_CLUSTER0, 0x0001030A, "cpu-cluster.0")
DEFINE_CLK_STUB(HI3660_CLK_STUB_CLUSTER1, 0x0002030A, "cpu-cluster.1")
DEFINE_CLK_STUB(HI3660_CLK_STUB_GPU, 0x0003030A, "clk-g3d")
DEFINE_CLK_STUB(HI3660_CLK_STUB_DDR, 0x00040309, "clk-ddrc")
};
static struct clk_hw *hi3660_stub_clk_hw_get(struct of_phandle_args *clkspec,
void *data)
{
unsigned int idx = clkspec->args[0];
if (idx >= HI3660_CLK_STUB_NUM) {
pr_err("%s: invalid index %u\n", __func__, idx);
return ERR_PTR(-EINVAL);
}
return &hi3660_stub_clks[idx].hw;
}
static int hi3660_stub_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
unsigned int i;
int ret;
/* Use mailbox client without blocking */
stub_clk_chan.cl.dev = dev;
stub_clk_chan.cl.tx_done = NULL;
stub_clk_chan.cl.tx_block = false;
stub_clk_chan.cl.knows_txdone = false;
/* Allocate mailbox channel */
stub_clk_chan.mbox = mbox_request_channel(&stub_clk_chan.cl, 0);
if (IS_ERR(stub_clk_chan.mbox))
return PTR_ERR(stub_clk_chan.mbox);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
freq_reg = devm_ioremap(dev, res->start, resource_size(res));
if (!freq_reg)
return -ENOMEM;
freq_reg += HI3660_STUB_CLOCK_DATA;
for (i = 0; i < HI3660_CLK_STUB_NUM; i++) {
ret = devm_clk_hw_register(&pdev->dev, &hi3660_stub_clks[i].hw);
if (ret)
return ret;
}
return devm_of_clk_add_hw_provider(&pdev->dev, hi3660_stub_clk_hw_get,
hi3660_stub_clks);
}
static const struct of_device_id hi3660_stub_clk_of_match[] = {
{ .compatible = "hisilicon,hi3660-stub-clk", },
{}
};
static struct platform_driver hi3660_stub_clk_driver = {
.probe = hi3660_stub_clk_probe,
.driver = {
.name = "hi3660-stub-clk",
.of_match_table = hi3660_stub_clk_of_match,
},
};
static int __init hi3660_stub_clk_init(void)
{
return platform_driver_register(&hi3660_stub_clk_driver);
}
subsys_initcall(hi3660_stub_clk_init);
......@@ -56,7 +56,7 @@ static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
val &= div_mask(dclk->width);
return divider_recalc_rate(hw, parent_rate, val, dclk->table,
CLK_DIVIDER_ROUND_CLOSEST);
CLK_DIVIDER_ROUND_CLOSEST, dclk->width);
}
static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
......
......@@ -257,10 +257,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
clk[IMX5_CLK_VPU_SEL] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
clk[IMX5_CLK_VPU_GATE] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
clk[IMX5_CLK_VPU_REFERENCE_GATE] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[IMX5_CLK_GPC_DVFS] = imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
clk[IMX5_CLK_SSI_APM] = imx_clk_mux("ssi_apm", MXC_CCM_CSCMR1, 8, 2, ssi_apm_sels, ARRAY_SIZE(ssi_apm_sels));
......@@ -361,6 +357,10 @@ static void __init mx50_clocks_init(struct device_node *np)
clk[IMX5_CLK_USB_PHY1_GATE] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
clk[IMX5_CLK_USB_PHY2_GATE] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
clk[IMX5_CLK_I2C3_GATE] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
......@@ -562,6 +562,10 @@ static void __init mx53_clocks_init(struct device_node *np)
clk[IMX5_CLK_IEEE1588_PRED] = imx_clk_divider("ieee1588_pred", "ieee1588_sel", MXC_CCM_CSCDR2, 6, 3);
clk[IMX5_CLK_IEEE1588_PODF] = imx_clk_divider("ieee1588_podf", "ieee1588_pred", MXC_CCM_CSCDR2, 0, 6);
clk[IMX5_CLK_IEEE1588_GATE] = imx_clk_gate2("ieee1588_serial_gate", "ieee1588_podf", MXC_CCM_CCGR7, 6);
clk[IMX5_CLK_UART4_IPG_GATE] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
clk[IMX5_CLK_UART4_PER_GATE] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
clk[IMX5_CLK_UART5_IPG_GATE] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
clk[IMX5_CLK_UART5_PER_GATE] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
......
#
# MediaTek SoC drivers
# MediaTek Clock Drivers
#
menu "Clock driver for MediaTek SoC"
depends on ARCH_MEDIATEK || COMPILE_TEST
config COMMON_CLK_MEDIATEK
bool
select RESET_CONTROLLER
---help---
Mediatek SoCs' clock support.
MediaTek SoCs' clock support.
config COMMON_CLK_MT2701
bool "Clock driver for Mediatek MT2701"
bool "Clock driver for MediaTek MT2701"
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM
---help---
This driver supports Mediatek MT2701 basic clocks.
This driver supports MediaTek MT2701 basic clocks.
config COMMON_CLK_MT2701_MMSYS
bool "Clock driver for Mediatek MT2701 mmsys"
bool "Clock driver for MediaTek MT2701 mmsys"
depends on COMMON_CLK_MT2701
---help---
This driver supports Mediatek MT2701 mmsys clocks.
This driver supports MediaTek MT2701 mmsys clocks.
config COMMON_CLK_MT2701_IMGSYS
bool "Clock driver for Mediatek MT2701 imgsys"
bool "Clock driver for MediaTek MT2701 imgsys"
depends on COMMON_CLK_MT2701
---help---
This driver supports Mediatek MT2701 imgsys clocks.
This driver supports MediaTek MT2701 imgsys clocks.
config COMMON_CLK_MT2701_VDECSYS
bool "Clock driver for Mediatek MT2701 vdecsys"
bool "Clock driver for MediaTek MT2701 vdecsys"
depends on COMMON_CLK_MT2701
---help---
This driver supports Mediatek MT2701 vdecsys clocks.
This driver supports MediaTek MT2701 vdecsys clocks.
config COMMON_CLK_MT2701_HIFSYS
bool "Clock driver for Mediatek MT2701 hifsys"
bool "Clock driver for MediaTek MT2701 hifsys"
depends on COMMON_CLK_MT2701
---help---
This driver supports Mediatek MT2701 hifsys clocks.
This driver supports MediaTek MT2701 hifsys clocks.
config COMMON_CLK_MT2701_ETHSYS
bool "Clock driver for Mediatek MT2701 ethsys"
bool "Clock driver for MediaTek MT2701 ethsys"
depends on COMMON_CLK_MT2701
---help---
This driver supports Mediatek MT2701 ethsys clocks.
This driver supports MediaTek MT2701 ethsys clocks.
config COMMON_CLK_MT2701_BDPSYS
bool "Clock driver for Mediatek MT2701 bdpsys"
bool "Clock driver for MediaTek MT2701 bdpsys"
depends on COMMON_CLK_MT2701
---help---
This driver supports Mediatek MT2701 bdpsys clocks.
This driver supports MediaTek MT2701 bdpsys clocks.
config COMMON_CLK_MT2712
bool "Clock driver for Mediatek MT2712"
bool "Clock driver for MediaTek MT2712"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
---help---
This driver supports Mediatek MT2712 basic clocks.
This driver supports MediaTek MT2712 basic clocks.
config COMMON_CLK_MT2712_BDPSYS
bool "Clock driver for Mediatek MT2712 bdpsys"
bool "Clock driver for MediaTek MT2712 bdpsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 bdpsys clocks.
This driver supports MediaTek MT2712 bdpsys clocks.
config COMMON_CLK_MT2712_IMGSYS
bool "Clock driver for Mediatek MT2712 imgsys"
bool "Clock driver for MediaTek MT2712 imgsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 imgsys clocks.
This driver supports MediaTek MT2712 imgsys clocks.
config COMMON_CLK_MT2712_JPGDECSYS
bool "Clock driver for Mediatek MT2712 jpgdecsys"
bool "Clock driver for MediaTek MT2712 jpgdecsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 jpgdecsys clocks.
This driver supports MediaTek MT2712 jpgdecsys clocks.
config COMMON_CLK_MT2712_MFGCFG
bool "Clock driver for Mediatek MT2712 mfgcfg"
bool "Clock driver for MediaTek MT2712 mfgcfg"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 mfgcfg clocks.
This driver supports MediaTek MT2712 mfgcfg clocks.
config COMMON_CLK_MT2712_MMSYS
bool "Clock driver for Mediatek MT2712 mmsys"
bool "Clock driver for MediaTek MT2712 mmsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 mmsys clocks.
This driver supports MediaTek MT2712 mmsys clocks.
config COMMON_CLK_MT2712_VDECSYS
bool "Clock driver for Mediatek MT2712 vdecsys"
bool "Clock driver for MediaTek MT2712 vdecsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 vdecsys clocks.
This driver supports MediaTek MT2712 vdecsys clocks.
config COMMON_CLK_MT2712_VENCSYS
bool "Clock driver for Mediatek MT2712 vencsys"
bool "Clock driver for MediaTek MT2712 vencsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 vencsys clocks.
This driver supports MediaTek MT2712 vencsys clocks.
config COMMON_CLK_MT6797
bool "Clock driver for Mediatek MT6797"
bool "Clock driver for MediaTek MT6797"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
---help---
This driver supports Mediatek MT6797 basic clocks.
This driver supports MediaTek MT6797 basic clocks.
config COMMON_CLK_MT6797_MMSYS
bool "Clock driver for Mediatek MT6797 mmsys"
bool "Clock driver for MediaTek MT6797 mmsys"
depends on COMMON_CLK_MT6797
---help---
This driver supports Mediatek MT6797 mmsys clocks.
This driver supports MediaTek MT6797 mmsys clocks.
config COMMON_CLK_MT6797_IMGSYS
bool "Clock driver for Mediatek MT6797 imgsys"
bool "Clock driver for MediaTek MT6797 imgsys"
depends on COMMON_CLK_MT6797
---help---
This driver supports Mediatek MT6797 imgsys clocks.
This driver supports MediaTek MT6797 imgsys clocks.
config COMMON_CLK_MT6797_VDECSYS
bool "Clock driver for Mediatek MT6797 vdecsys"
bool "Clock driver for MediaTek MT6797 vdecsys"
depends on COMMON_CLK_MT6797
---help---
This driver supports Mediatek MT6797 vdecsys clocks.
This driver supports MediaTek MT6797 vdecsys clocks.
config COMMON_CLK_MT6797_VENCSYS
bool "Clock driver for Mediatek MT6797 vencsys"
bool "Clock driver for MediaTek MT6797 vencsys"
depends on COMMON_CLK_MT6797
---help---
This driver supports Mediatek MT6797 vencsys clocks.
This driver supports MediaTek MT6797 vencsys clocks.
config COMMON_CLK_MT7622
bool "Clock driver for MediaTek MT7622"
......@@ -163,17 +167,18 @@ config COMMON_CLK_MT7622_AUDSYS
to audio consumers such as I2S and TDM.
config COMMON_CLK_MT8135
bool "Clock driver for Mediatek MT8135"
bool "Clock driver for MediaTek MT8135"
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM
---help---
This driver supports Mediatek MT8135 clocks.
This driver supports MediaTek MT8135 clocks.
config COMMON_CLK_MT8173
bool "Clock driver for Mediatek MT8173"
bool "Clock driver for MediaTek MT8173"
depends on ARCH_MEDIATEK || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
---help---
This driver supports Mediatek MT8173 clocks.
This driver supports MediaTek MT8173 clocks.
endmenu
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
......
......@@ -20,6 +20,7 @@
#include <linux/clk-provider.h>
struct clk;
struct clk_onecell_data;
#define MAX_MUX_GATE_BIT 31
#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
......@@ -228,14 +229,7 @@ void mtk_clk_register_plls(struct device_node *node,
struct clk *mtk_clk_register_ref2usb_tx(const char *name,
const char *parent_name, void __iomem *reg);
#ifdef CONFIG_RESET_CONTROLLER
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs);
#else
static inline void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs)
{
}
#endif
#endif /* __DRV_CLK_MTK_H */
......@@ -19,3 +19,11 @@ config COMMON_CLK_GXBB
help
Support for the clock controller on AmLogic S905 devices, aka gxbb.
Say Y if you want peripherals and CPU frequency scaling to work.
config COMMON_CLK_AXG
bool
depends on COMMON_CLK_AMLOGIC
select RESET_CONTROLLER
help
Support for the clock controller on AmLogic A113D devices, aka axg.
Say Y if you want peripherals and CPU frequency scaling to work.
......@@ -5,3 +5,4 @@
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o
obj-$(CONFIG_COMMON_CLK_AXG) += axg.o
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2016 AmLogic, Inc.
* Author: Michael Turquette <mturquette@baylibre.com>
*
* Copyright (c) 2017 Amlogic, inc.
* Author: Qiufang Dai <qiufang.dai@amlogic.com>
*
*/
#ifndef __AXG_H
#define __AXG_H
/*
* Clock controller register offsets
*
* Register offsets from the data sheet must be multiplied by 4 before
* adding them to the base address to get the right value.
*/
#define HHI_GP0_PLL_CNTL 0x40
#define HHI_GP0_PLL_CNTL2 0x44
#define HHI_GP0_PLL_CNTL3 0x48
#define HHI_GP0_PLL_CNTL4 0x4c
#define HHI_GP0_PLL_CNTL5 0x50
#define HHI_GP0_PLL_STS 0x54
#define HHI_GP0_PLL_CNTL1 0x58
#define HHI_HIFI_PLL_CNTL 0x80
#define HHI_HIFI_PLL_CNTL2 0x84
#define HHI_HIFI_PLL_CNTL3 0x88
#define HHI_HIFI_PLL_CNTL4 0x8C
#define HHI_HIFI_PLL_CNTL5 0x90
#define HHI_HIFI_PLL_STS 0x94
#define HHI_HIFI_PLL_CNTL1 0x98
#define HHI_XTAL_DIVN_CNTL 0xbc
#define HHI_GCLK2_MPEG0 0xc0
#define HHI_GCLK2_MPEG1 0xc4
#define HHI_GCLK2_MPEG2 0xc8
#define HHI_GCLK2_OTHER 0xd0
#define HHI_GCLK2_AO 0xd4
#define HHI_PCIE_PLL_CNTL 0xd8
#define HHI_PCIE_PLL_CNTL1 0xdC
#define HHI_PCIE_PLL_CNTL2 0xe0
#define HHI_PCIE_PLL_CNTL3 0xe4
#define HHI_PCIE_PLL_CNTL4 0xe8
#define HHI_PCIE_PLL_CNTL5 0xec
#define HHI_PCIE_PLL_CNTL6 0xf0
#define HHI_PCIE_PLL_STS 0xf4
#define HHI_MEM_PD_REG0 0x100
#define HHI_VPU_MEM_PD_REG0 0x104
#define HHI_VIID_CLK_DIV 0x128
#define HHI_VIID_CLK_CNTL 0x12c
#define HHI_GCLK_MPEG0 0x140
#define HHI_GCLK_MPEG1 0x144
#define HHI_GCLK_MPEG2 0x148
#define HHI_GCLK_OTHER 0x150
#define HHI_GCLK_AO 0x154
#define HHI_SYS_CPU_CLK_CNTL1 0x15c
#define HHI_SYS_CPU_RESET_CNTL 0x160
#define HHI_VID_CLK_DIV 0x164
#define HHI_SPICC_HCLK_CNTL 0x168
#define HHI_MPEG_CLK_CNTL 0x174
#define HHI_VID_CLK_CNTL 0x17c
#define HHI_TS_CLK_CNTL 0x190
#define HHI_VID_CLK_CNTL2 0x194
#define HHI_SYS_CPU_CLK_CNTL0 0x19c
#define HHI_VID_PLL_CLK_DIV 0x1a0
#define HHI_VPU_CLK_CNTL 0x1bC
#define HHI_VAPBCLK_CNTL 0x1F4
#define HHI_GEN_CLK_CNTL 0x228
#define HHI_VDIN_MEAS_CLK_CNTL 0x250
#define HHI_NAND_CLK_CNTL 0x25C
#define HHI_SD_EMMC_CLK_CNTL 0x264
#define HHI_MPLL_CNTL 0x280
#define HHI_MPLL_CNTL2 0x284
#define HHI_MPLL_CNTL3 0x288
#define HHI_MPLL_CNTL4 0x28C
#define HHI_MPLL_CNTL5 0x290
#define HHI_MPLL_CNTL6 0x294
#define HHI_MPLL_CNTL7 0x298
#define HHI_MPLL_CNTL8 0x29C
#define HHI_MPLL_CNTL9 0x2A0
#define HHI_MPLL_CNTL10 0x2A4
#define HHI_MPLL3_CNTL0 0x2E0
#define HHI_MPLL3_CNTL1 0x2E4
#define HHI_PLL_TOP_MISC 0x2E8
#define HHI_SYS_PLL_CNTL1 0x2FC
#define HHI_SYS_PLL_CNTL 0x300
#define HHI_SYS_PLL_CNTL2 0x304
#define HHI_SYS_PLL_CNTL3 0x308
#define HHI_SYS_PLL_CNTL4 0x30c
#define HHI_SYS_PLL_CNTL5 0x310
#define HHI_SYS_PLL_STS 0x314
#define HHI_DPLL_TOP_I 0x318
#define HHI_DPLL_TOP2_I 0x31C
/*
* CLKID index values
*
* These indices are entirely contrived and do not map onto the hardware.
* It has now been decided to expose everything by default in the DT header:
* include/dt-bindings/clock/axg-clkc.h. Only the clocks ids we don't want
* to expose, such as the internal muxes and dividers of composite clocks,
* will remain defined here.
*/
#define CLKID_MPEG_SEL 8
#define CLKID_MPEG_DIV 9
#define CLKID_SD_EMMC_B_CLK0_SEL 61
#define CLKID_SD_EMMC_B_CLK0_DIV 62
#define CLKID_SD_EMMC_C_CLK0_SEL 63
#define CLKID_SD_EMMC_C_CLK0_DIV 64
#define NR_CLKS 65
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/axg-clkc.h>
#endif /* __AXG_H */
......@@ -98,7 +98,7 @@ static void params_from_rate(unsigned long requested_rate,
*sdm = SDM_DEN - 1;
} else {
*n2 = div;
*sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
*sdm = DIV_ROUND_UP_ULL((u64)rem * SDM_DEN, requested_rate);
}
}
......
......@@ -134,7 +134,7 @@ struct meson_clk_audio_divider {
struct clk_gate _name = { \
.reg = (void __iomem *) _reg, \
.bit_idx = (_bit), \
.lock = &clk_lock, \
.lock = &meson_clk_lock, \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = &clk_gate_ops, \
......
This diff is collapsed.
......@@ -32,7 +32,7 @@
#include "clkc.h"
#include "meson8b.h"
static DEFINE_SPINLOCK(clk_lock);
static DEFINE_SPINLOCK(meson_clk_lock);
static void __iomem *clk_base;
......@@ -136,7 +136,7 @@ static struct meson_clk_pll meson8b_fixed_pll = {
.shift = 16,
.width = 2,
},
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &meson_clk_pll_ro_ops,
......@@ -162,7 +162,7 @@ static struct meson_clk_pll meson8b_vid_pll = {
.shift = 16,
.width = 2,
},
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vid_pll",
.ops = &meson_clk_pll_ro_ops,
......@@ -190,7 +190,7 @@ static struct meson_clk_pll meson8b_sys_pll = {
},
.rate_table = sys_pll_rate_table,
.rate_count = ARRAY_SIZE(sys_pll_rate_table),
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &meson_clk_pll_ops,
......@@ -281,7 +281,7 @@ static struct meson_clk_mpll meson8b_mpll0 = {
.shift = 25,
.width = 1,
},
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &meson_clk_mpll_ops,
......@@ -311,7 +311,7 @@ static struct meson_clk_mpll meson8b_mpll1 = {
.shift = 14,
.width = 1,
},
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &meson_clk_mpll_ops,
......@@ -341,7 +341,7 @@ static struct meson_clk_mpll meson8b_mpll2 = {
.shift = 14,
.width = 1,
},
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &meson_clk_mpll_ops,
......@@ -375,7 +375,7 @@ struct clk_mux meson8b_mpeg_clk_sel = {
.shift = 12,
.flags = CLK_MUX_READ_ONLY,
.table = mux_table_clk81,
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
.ops = &clk_mux_ro_ops,
......@@ -395,7 +395,7 @@ struct clk_divider meson8b_mpeg_clk_div = {
.reg = (void *)HHI_MPEG_CLK_CNTL,
.shift = 0,
.width = 7,
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_divider_ops,
......@@ -408,7 +408,7 @@ struct clk_divider meson8b_mpeg_clk_div = {
struct clk_gate meson8b_clk81 = {
.reg = (void *)HHI_MPEG_CLK_CNTL,
.bit_idx = 7,
.lock = &clk_lock,
.lock = &meson_clk_lock,
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_gate_ops,
......@@ -773,7 +773,7 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
reset = &meson8b_clk_reset_bits[id];
spin_lock_irqsave(&clk_lock, flags);
spin_lock_irqsave(&meson_clk_lock, flags);
val = readl(meson8b_clk_reset->base + reset->reg);
if (assert)
......@@ -782,7 +782,7 @@ static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev,
val &= ~BIT(reset->bit_idx);
writel(val, meson8b_clk_reset->base + reset->reg);
spin_unlock_irqrestore(&clk_lock, flags);
spin_unlock_irqrestore(&meson_clk_lock, flags);
return 0;
}
......
This diff is collapsed.
......@@ -526,7 +526,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
!(pll_is_valid(parent_rate, 1, 1000000, 20000000)
&& pll_is_valid(cco_rate, 1, 156000000, 320000000)
&& pll_is_valid(ref_rate, 1, 1000000, 27000000)))
pr_err("%s: PLL clocks are not in valid ranges: %lu/%lu/%lu",
pr_err("%s: PLL clocks are not in valid ranges: %lu/%lu/%lu\n",
clk_hw_get_name(hw),
parent_rate, cco_rate, ref_rate);
......@@ -956,7 +956,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
val &= div_mask(divider->width);
return divider_recalc_rate(hw, parent_rate, val, divider->table,
divider->flags);
divider->flags, divider->width);
}
static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
......@@ -1505,7 +1505,7 @@ static void __init lpc32xx_clk_init(struct device_node *np)
return;
}
if (clk_get_rate(clk_32k) != 32768) {
pr_err("invalid clock rate of external 32KHz oscillator");
pr_err("invalid clock rate of external 32KHz oscillator\n");
return;
}
......
......@@ -329,12 +329,16 @@ static void __init pxa3xx_dummy_clocks_init(void)
static void __init pxa3xx_base_clocks_init(void)
{
struct clk *clk;
pxa3xx_register_plls();
pxa3xx_register_core();
clk_register_clk_pxa3xx_system_bus();
clk_register_clk_pxa3xx_ac97();
clk_register_clk_pxa3xx_smemc();
clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0, OSCC, 11, 0, NULL);
clk = clk_register_gate(NULL, "CLK_POUT",
"osc_13mhz", 0, OSCC, 11, 0, NULL);
clk_register_clkdev(clk, "CLK_POUT", NULL);
clkdev_pxa_register(CLK_OSTIMER, "OSTIMER0", NULL,
clk_register_fixed_factor(NULL, "os-timer0",
"osc_13mhz", 0, 1, 4));
......
......@@ -12,6 +12,27 @@ config COMMON_CLK_QCOM
select REGMAP_MMIO
select RESET_CONTROLLER
config QCOM_A53PLL
tristate "MSM8916 A53 PLL"
depends on COMMON_CLK_QCOM
default ARCH_QCOM
help
Support for the A53 PLL on MSM8916 devices. It provides
the CPU with frequencies above 1GHz.
Say Y if you want to support higher CPU frequencies on MSM8916
devices.
config QCOM_CLK_APCS_MSM8916
tristate "MSM8916 APCS Clock Controller"
depends on COMMON_CLK_QCOM
depends on QCOM_APCS_IPC || COMPILE_TEST
default ARCH_QCOM
help
Support for the APCS Clock Controller on msm8916 devices. The
APCS is managing the mux and divider which feeds the CPUs.
Say Y if you want to support CPU frequency scaling on devices
such as msm8916.
config QCOM_CLK_RPM
tristate "RPM based Clock Controller"
depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
......@@ -196,3 +217,12 @@ config MSM_MMCC_8996
Support for the multimedia clock controller on msm8996 devices.
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
config SPMI_PMIC_CLKDIV
tristate "SPMI PMIC clkdiv Support"
depends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST
help
This driver supports the clkdiv functionality on the Qualcomm
Technologies, Inc. SPMI PMIC. It configures the frequency of
clkdiv outputs of the PMIC. These clocks are typically wired
through alternate functions on GPIO pins.
......@@ -10,6 +10,7 @@ clk-qcom-y += clk-rcg2.o
clk-qcom-y += clk-branch.o
clk-qcom-y += clk-regmap-divider.o
clk-qcom-y += clk-regmap-mux.o
clk-qcom-y += clk-regmap-mux-div.o
clk-qcom-y += reset.o
clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
......@@ -32,5 +33,8 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
// SPDX-License-Identifier: GPL-2.0
/*
* Qualcomm A53 PLL driver
*
* Copyright (c) 2017, Linaro Limited
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/module.h>
#include "clk-pll.h"
#include "clk-regmap.h"
static const struct pll_freq_tbl a53pll_freq[] = {
{ 998400000, 52, 0x0, 0x1, 0 },
{ 1094400000, 57, 0x0, 0x1, 0 },
{ 1152000000, 62, 0x0, 0x1, 0 },
{ 1209600000, 63, 0x0, 0x1, 0 },
{ 1248000000, 65, 0x0, 0x1, 0 },
{ 1363200000, 71, 0x0, 0x1, 0 },
{ 1401600000, 73, 0x0, 0x1, 0 },
{ }
};
static const struct regmap_config a53pll_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x40,
.fast_io = true,
};
static int qcom_a53pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regmap *regmap;
struct resource *res;
struct clk_pll *pll;
void __iomem *base;
struct clk_init_data init = { };
int ret;
pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
if (!pll)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(dev, base, &a53pll_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
pll->l_reg = 0x04;
pll->m_reg = 0x08;
pll->n_reg = 0x0c;
pll->config_reg = 0x14;
pll->mode_reg = 0x00;
pll->status_reg = 0x1c;
pll->status_bit = 16;
pll->freq_tbl = a53pll_freq;
init.name = "a53pll";
init.parent_names = (const char *[]){ "xo" };
init.num_parents = 1;
init.ops = &clk_pll_sr2_ops;
init.flags = CLK_IS_CRITICAL;
pll->clkr.hw.init = &init;
ret = devm_clk_register_regmap(dev, &pll->clkr);
if (ret) {
dev_err(dev, "failed to register regmap clock: %d\n", ret);
return ret;
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&pll->clkr.hw);
if (ret) {
dev_err(dev, "failed to add clock provider: %d\n", ret);
return ret;
}
return 0;
}
static const struct of_device_id qcom_a53pll_match_table[] = {
{ .compatible = "qcom,msm8916-a53pll" },
{ }
};
static struct platform_driver qcom_a53pll_driver = {
.probe = qcom_a53pll_probe,
.driver = {
.name = "qcom-a53pll",
.of_match_table = qcom_a53pll_match_table,
},
};
module_platform_driver(qcom_a53pll_driver);
MODULE_DESCRIPTION("Qualcomm A53 PLL Driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -25,16 +25,6 @@ struct freq_tbl {
u16 n;
};
/**
* struct parent_map - map table for PLL source select configuration values
* @src: source PLL
* @cfg: configuration value
*/
struct parent_map {
u8 src;
u8 cfg;
};
/**
* struct mn - M/N:D counter
* @mnctr_en_bit: bit to enable mn counter
......
......@@ -23,6 +23,29 @@ static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw)
return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr);
}
static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
struct clk_regmap *clkr = &divider->clkr;
u32 div;
struct clk_hw *hw_parent = clk_hw_get_parent(hw);
regmap_read(clkr->regmap, divider->reg, &div);
div >>= divider->shift;
div &= BIT(divider->width) - 1;
div += 1;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
if (!hw_parent)
return -EINVAL;
*prate = clk_hw_round_rate(hw_parent, rate * div);
}
return DIV_ROUND_UP_ULL((u64)*prate, div);
}
static long div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
......@@ -59,7 +82,7 @@ static unsigned long div_recalc_rate(struct clk_hw *hw,
div &= BIT(divider->width) - 1;
return divider_recalc_rate(hw, parent_rate, div, NULL,
CLK_DIVIDER_ROUND_CLOSEST);
CLK_DIVIDER_ROUND_CLOSEST, divider->width);
}
const struct clk_ops clk_regmap_div_ops = {
......@@ -68,3 +91,9 @@ const struct clk_ops clk_regmap_div_ops = {
.recalc_rate = div_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_div_ops);
const struct clk_ops clk_regmap_div_ro_ops = {
.round_rate = div_round_ro_rate,
.recalc_rate = div_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_div_ro_ops);
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