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

clk: qcom: Add A53 PLL support

The CPUs on Qualcomm MSM8916-based platforms are clocked by two PLLs,
a primary (A53) CPU PLL and a secondary fixed-rate GPLL0. These sources
are connected to a mux and half-integer divider, which is feeding the
CPU cores.

This patch adds support for the primary CPU PLL which generates the
higher range of frequencies above 1GHz.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Tested-by: Amit Kucheria <amit.kucheria@linaro.org>
[sboyd@codeaurora.org: Move to devm provider registration,
NUL terminate frequency table, made tristate/modular]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

authored by

Georgi Djakov and committed by
Stephen Boyd
0c6ab1b8 4fbd8d19

+140
+22
Documentation/devicetree/bindings/clock/qcom,a53pll.txt
··· 1 + Qualcomm MSM8916 A53 PLL Binding 2 + -------------------------------- 3 + The A53 PLL on MSM8916 platforms is the main CPU PLL used used for frequencies 4 + above 1GHz. 5 + 6 + Required properties : 7 + - compatible : Shall contain only one of the following: 8 + 9 + "qcom,msm8916-a53pll" 10 + 11 + - reg : shall contain base register location and length 12 + 13 + - #clock-cells : must be set to <0> 14 + 15 + Example: 16 + 17 + a53pll: clock@b016000 { 18 + compatible = "qcom,msm8916-a53pll"; 19 + reg = <0xb016000 0x40>; 20 + #clock-cells = <0>; 21 + }; 22 +
+10
drivers/clk/qcom/Kconfig
··· 12 12 select REGMAP_MMIO 13 13 select RESET_CONTROLLER 14 14 15 + config QCOM_A53PLL 16 + tristate "MSM8916 A53 PLL" 17 + depends on COMMON_CLK_QCOM 18 + default ARCH_QCOM 19 + help 20 + Support for the A53 PLL on MSM8916 devices. It provides 21 + the CPU with frequencies above 1GHz. 22 + Say Y if you want to support higher CPU frequencies on MSM8916 23 + devices. 24 + 15 25 config QCOM_CLK_RPM 16 26 tristate "RPM based Clock Controller" 17 27 depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
+1
drivers/clk/qcom/Makefile
··· 32 32 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o 33 33 obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o 34 34 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o 35 + obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o 35 36 obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o 36 37 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
+107
drivers/clk/qcom/a53-pll.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Qualcomm A53 PLL driver 4 + * 5 + * Copyright (c) 2017, Linaro Limited 6 + * Author: Georgi Djakov <georgi.djakov@linaro.org> 7 + */ 8 + 9 + #include <linux/clk-provider.h> 10 + #include <linux/kernel.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/regmap.h> 13 + #include <linux/module.h> 14 + 15 + #include "clk-pll.h" 16 + #include "clk-regmap.h" 17 + 18 + static const struct pll_freq_tbl a53pll_freq[] = { 19 + { 998400000, 52, 0x0, 0x1, 0 }, 20 + { 1094400000, 57, 0x0, 0x1, 0 }, 21 + { 1152000000, 62, 0x0, 0x1, 0 }, 22 + { 1209600000, 63, 0x0, 0x1, 0 }, 23 + { 1248000000, 65, 0x0, 0x1, 0 }, 24 + { 1363200000, 71, 0x0, 0x1, 0 }, 25 + { 1401600000, 73, 0x0, 0x1, 0 }, 26 + { } 27 + }; 28 + 29 + static const struct regmap_config a53pll_regmap_config = { 30 + .reg_bits = 32, 31 + .reg_stride = 4, 32 + .val_bits = 32, 33 + .max_register = 0x40, 34 + .fast_io = true, 35 + }; 36 + 37 + static int qcom_a53pll_probe(struct platform_device *pdev) 38 + { 39 + struct device *dev = &pdev->dev; 40 + struct regmap *regmap; 41 + struct resource *res; 42 + struct clk_pll *pll; 43 + void __iomem *base; 44 + struct clk_init_data init = { }; 45 + int ret; 46 + 47 + pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); 48 + if (!pll) 49 + return -ENOMEM; 50 + 51 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 52 + base = devm_ioremap_resource(dev, res); 53 + if (IS_ERR(base)) 54 + return PTR_ERR(base); 55 + 56 + regmap = devm_regmap_init_mmio(dev, base, &a53pll_regmap_config); 57 + if (IS_ERR(regmap)) 58 + return PTR_ERR(regmap); 59 + 60 + pll->l_reg = 0x04; 61 + pll->m_reg = 0x08; 62 + pll->n_reg = 0x0c; 63 + pll->config_reg = 0x14; 64 + pll->mode_reg = 0x00; 65 + pll->status_reg = 0x1c; 66 + pll->status_bit = 16; 67 + pll->freq_tbl = a53pll_freq; 68 + 69 + init.name = "a53pll"; 70 + init.parent_names = (const char *[]){ "xo" }; 71 + init.num_parents = 1; 72 + init.ops = &clk_pll_sr2_ops; 73 + init.flags = CLK_IS_CRITICAL; 74 + pll->clkr.hw.init = &init; 75 + 76 + ret = devm_clk_register_regmap(dev, &pll->clkr); 77 + if (ret) { 78 + dev_err(dev, "failed to register regmap clock: %d\n", ret); 79 + return ret; 80 + } 81 + 82 + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, 83 + &pll->clkr.hw); 84 + if (ret) { 85 + dev_err(dev, "failed to add clock provider: %d\n", ret); 86 + return ret; 87 + } 88 + 89 + return 0; 90 + } 91 + 92 + static const struct of_device_id qcom_a53pll_match_table[] = { 93 + { .compatible = "qcom,msm8916-a53pll" }, 94 + { } 95 + }; 96 + 97 + static struct platform_driver qcom_a53pll_driver = { 98 + .probe = qcom_a53pll_probe, 99 + .driver = { 100 + .name = "qcom-a53pll", 101 + .of_match_table = qcom_a53pll_match_table, 102 + }, 103 + }; 104 + module_platform_driver(qcom_a53pll_driver); 105 + 106 + MODULE_DESCRIPTION("Qualcomm A53 PLL Driver"); 107 + MODULE_LICENSE("GPL v2");